![](/img/trans.png)
[英]How do I get the WindowsPrincipal when hosting OWIN/Katana inside IIS?
[英]Owin Unauthorised when hosting more web apis inside IIS website
讓我們描述一下我的體系結構,我有一個根IIS WebSite,然后是Web Api,其中使用Owin進行身份驗證,然后是AngularJS前端,另一個Web Api來為該前端提供服務器。 看起來像:
Website(root) -
Auth(Web API Owin)
Front-End(AngularJS) -
Service(Web API)
我的問題如下:-我可以從前端的Web Api Owin應用程序獲取令牌-當我嘗試對服務Web api“服務”的控制器使用此令牌時,得到未經授權的響應
我嘗試了Web api身份驗證的各種配置組合,所有站點都在同一台計算機上,我不在web.config中使用MachineKey。
配置如下:Web Api Owin:
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static string PublicClientId { get; private set; }
public void ConfigureAuth(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
OAuthBearerAuthenticationOptions OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
AllowInsecureHttp = true
};
app.UseOAuthAuthorizationServer(OAuthOptions);
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
}
}
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
服務網絡API:
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static string PublicClientId { get; private set; }
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
OAuthBearerAuthenticationOptions OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
}
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
// use cors with signalR
app.Map("/signalr", map =>
{
// Setup the CORS middleware to run before SignalR.
// By default this will allow all origins. You can
// configure the set of origins and/or http verbs by
// providing a cors options with a different policy.
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableDetailedErrors = true
// You can enable JSONP by uncommenting line below.
// JSONP requests are insecure but some older browsers (and some
// versions of IE) require JSONP to work cross domain
// EnableJSONP = true
};
// Run the SignalR pipeline. We're not using MapSignalR
// since this branch already runs under the "/signalr"
// path.
map.RunSignalR(hubConfiguration);
});
}
}
我正在使用自己的OAuthProvider,如下所示:
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
private readonly string _publicClientId;
public ApplicationOAuthProvider(string publicClientId)
{
if (publicClientId == null)
{
throw new ArgumentNullException("publicClientId");
}
_publicClientId = publicClientId;
}
public override Task MatchEndpoint(OAuthMatchEndpointContext context)
{
if (context.IsTokenEndpoint && context.Request.Method == "OPTIONS")
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "authorization" });
context.RequestCompleted();
return Task.FromResult(0);
}
return base.MatchEndpoint(context);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
if (!context.OwinContext.Response.Headers.ContainsKey("Access-Control-Allow-Origin"))
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
if (user.Roles != null && user.Roles.Count != 0)
oAuthIdentity.AddClaim(new Claim(ClaimTypes.Role, user.Roles.Select(r => r.RoleId).Aggregate((acc, r) => acc + ";" + r)));
oAuthIdentity.AddClaim(new Claim("TwoFactorExpiration", user.TwoFactorExpiration.ToString()));
ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user.UserName);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
{
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
return Task.FromResult<object>(null);
}
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// Resource owner password credentials does not provide a client ID.
if (context.ClientId == null)
{
context.Validated();
}
return Task.FromResult<object>(null);
}
public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (context.ClientId == _publicClientId)
{
Uri expectedRootUri = new Uri(context.Request.Uri, "/");
if (expectedRootUri.AbsoluteUri == context.RedirectUri)
{
context.Validated();
}
}
return Task.FromResult<object>(null);
}
public static AuthenticationProperties CreateProperties(string userName)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName }
};
return new AuthenticationProperties(data);
}
}
如您所見,我也在服務Web API上使用了SignalR。 如果每個Web API在IIS上都有自己的網站,那么所有方法都可以正常工作。
我究竟做錯了什么? 我知道我錯過了一些東西。 目的是使用一個Web api owin應用程序對許多Web api進行授權,如您所見,我也在其中定義了基於角色的身份驗證。
感謝您的任何投入。
更新1:當我嘗試通過Visual Studio調試IIS網站時,在調試窗口中收到以下消息:
System.Web.dll中發生類型'System.Security.Cryptography.CryptographicException'的第一次機會異常
...
w3wp.exe信息:0:操作= AuthorizeAttribute.OnAuthorizationAsync,狀態= 401(未授權)
w3wp.exe的信息:0:消息= '所選動作'獲取(可空1 affiliateId, Nullable
1日)'',操作= ApiControllerActionSelector.SelectAction
w3wp.exe信息:0:Operation = AffiliatesController.ExecuteAsync,Status = 401(未經授權)
w3wp.exe信息:0:消息=“將使用相同的'JsonMediaTypeFormatter'格式化程序”,Operation = JsonMediaTypeFormatter.GetPerRequestFormatterInstance
w3wp.exe信息:0:操作= CorsMessageHandler.SendAsync,狀態= 401(未經授權)
w3wp.exe信息:0:消息=“選定的格式化程序='JsonMediaTypeFormatter',content-type ='application / json; charset = utf-8'',Operation = DefaultContentNegotiator.Negotiate
w3wp.exe信息:0:操作= AuthorizeAttribute.OnAuthorizationAsync,狀態= 401(未授權)
我找到了解決方案,即使您的解決方案在同一台機器上,您也必須為您的機器創建機器密鑰並將其附加到您的Web配置中,請執行以下步驟5: http : //bitoftech.net/2014/09/24 / decouple-owin-authorization-server-resource-server-oauth-2-0-web-api /
我仍然不知道為什么每個Web api都有自己的IIS網站時,它為什么能正常工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.