Asp.net core 2.0+ - 多重身份验证方案(Cookie / Bearer)
Asp.net core 2.0+ - Multiple Authentication Schemes (Cookie / Bearer)
我一直在努力让多个身份验证方案在 Asp.net 核心 2.1 中正常工作。
我正在使用带有隐式流的身份服务器和 OpenIdConnect 作为协议。
仅使用其中一种方案(例如 Cookie 或 Bearer)授权操作或控制器时,该功能可以正常工作。
示例:
[Authorize(AuthenticationSchemes = "Cookies")]
[Route("Cookies")]
public class BearerAndCookiesController : Controller {
如果我在授权属性上同时指定了这两种方案,那么它会部分失败。 Bearer 正常工作,但当我尝试在浏览器中查看页面时,它会尝试重定向到本地登录页面 (http://localhost/Account/Login)。
当我检查 Identity Server 的调试日志时,没有返回任何内容,这是有道理的,因为它没有尝试联系管理局。然而,当我查看测试 MVC 站点的调试日志时,Bearer 和 Cookie 方案都受到挑战:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5002/cookies
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Get", controller = "BearerAndCookies"}. Executing action MvcClient.Controllers.BearerAndCookiesController.Get (MvcClient)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes (Bearer, Cookies).
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: Bearer was challenged.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action MvcClient.Controllers.BearerAndCookiesController.Get (MvcClient) in 68.1922ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 93.2016ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5002/Account/Login?ReturnUrl=%2Fcookies
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 30.2532ms 404
Failed to load resource: the server responded with a status of 404 (Not Found) [http://localhost:5002/Account/Login?ReturnUrl=%2Fcookies]
有谁知道为什么这不起作用?我要请人喝啤酒!上周它一直在找我。
这是我的 Startup.cs 配置:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options => {
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddJwtBearer(options => {
options.Authority = "http://localhost:5000";
options.Audience = "myApi";
options.RequireHttpsMetadata = false;
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options => {
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "myApi";
options.SaveTokens = true;
});
}
[Authorize(AuthenticationSchemes = AuthSchemes)]
[Route("Cookies")]
public class BearerAndCookiesController : Controller {
private const string AuthSchemes =
JwtBearerDefaults.AuthenticationScheme + "," +
CookieAuthenticationDefaults.AuthenticationScheme;
我想更好地解释这个答案:
- 我不得不移动 services.AddAuthorization 那部分是我
添加了这两个方案。这确保两个方案都已注册
正确。
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options => {
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options => {
options.SignInScheme = "Cookies";
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "myApi";
options.SaveTokens = true;
}).AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options => {
options.Authority = "http://localhost:5000";
options.ApiName = "myApi";
options.RequireHttpsMetadata = false;
});
services.AddAuthorization(options => {
...
});
- 然后而不是将授权方案指定为
Controller Action Authorize标签,我在使用的时候使用了全局策略
services.AddAuthorization
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
CookieAuthenticationDefaults.AuthenticationScheme,
JwtBearerDefaults.AuthenticationScheme);
defaultAuthorizationPolicyBuilder =
defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
- 当我导航到 API 的任何部分时,它不会重定向到登录屏幕。我注意到,如果您首先通过导航到 Identity Server 登录,然后返回该页面,它实际上会像往常一样对您进行身份验证。所以我加入了一些感觉有点像 hack 的东西。重要的是,这直接进入 app.UseAuthentication.
app.UseAuthentication();
app.Use(async (context, next) => {
await next();
var bearerAuth = context.Request.Headers["Authorization"]
.FirstOrDefault()?.StartsWith("Bearer ") ?? false;
if (context.Response.StatusCode == 401
&& !context.User.Identity.IsAuthenticated
&& !bearerAuth) {
await context.ChallengeAsync("oidc");
}
});
Bob 是你的叔叔...感谢这位 post 的大力帮助!! oipapio.com/question-1510997
我一直在努力让多个身份验证方案在 Asp.net 核心 2.1 中正常工作。
我正在使用带有隐式流的身份服务器和 OpenIdConnect 作为协议。
仅使用其中一种方案(例如 Cookie 或 Bearer)授权操作或控制器时,该功能可以正常工作。
示例:
[Authorize(AuthenticationSchemes = "Cookies")]
[Route("Cookies")]
public class BearerAndCookiesController : Controller {
如果我在授权属性上同时指定了这两种方案,那么它会部分失败。 Bearer 正常工作,但当我尝试在浏览器中查看页面时,它会尝试重定向到本地登录页面 (http://localhost/Account/Login)。
当我检查 Identity Server 的调试日志时,没有返回任何内容,这是有道理的,因为它没有尝试联系管理局。然而,当我查看测试 MVC 站点的调试日志时,Bearer 和 Cookie 方案都受到挑战:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5002/cookies
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Get", controller = "BearerAndCookies"}. Executing action MvcClient.Controllers.BearerAndCookiesController.Get (MvcClient)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes (Bearer, Cookies).
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: Bearer was challenged.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action MvcClient.Controllers.BearerAndCookiesController.Get (MvcClient) in 68.1922ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 93.2016ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5002/Account/Login?ReturnUrl=%2Fcookies
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 30.2532ms 404
Failed to load resource: the server responded with a status of 404 (Not Found) [http://localhost:5002/Account/Login?ReturnUrl=%2Fcookies]
有谁知道为什么这不起作用?我要请人喝啤酒!上周它一直在找我。
这是我的 Startup.cs 配置:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options => {
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddJwtBearer(options => {
options.Authority = "http://localhost:5000";
options.Audience = "myApi";
options.RequireHttpsMetadata = false;
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options => {
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "myApi";
options.SaveTokens = true;
});
}
[Authorize(AuthenticationSchemes = AuthSchemes)]
[Route("Cookies")]
public class BearerAndCookiesController : Controller {
private const string AuthSchemes =
JwtBearerDefaults.AuthenticationScheme + "," +
CookieAuthenticationDefaults.AuthenticationScheme;
我想更好地解释这个答案:
- 我不得不移动 services.AddAuthorization 那部分是我 添加了这两个方案。这确保两个方案都已注册 正确。
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options => {
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options => {
options.SignInScheme = "Cookies";
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "myApi";
options.SaveTokens = true;
}).AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options => {
options.Authority = "http://localhost:5000";
options.ApiName = "myApi";
options.RequireHttpsMetadata = false;
});
services.AddAuthorization(options => {
...
});
- 然后而不是将授权方案指定为 Controller Action Authorize标签,我在使用的时候使用了全局策略 services.AddAuthorization
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
CookieAuthenticationDefaults.AuthenticationScheme,
JwtBearerDefaults.AuthenticationScheme);
defaultAuthorizationPolicyBuilder =
defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
- 当我导航到 API 的任何部分时,它不会重定向到登录屏幕。我注意到,如果您首先通过导航到 Identity Server 登录,然后返回该页面,它实际上会像往常一样对您进行身份验证。所以我加入了一些感觉有点像 hack 的东西。重要的是,这直接进入 app.UseAuthentication.
app.UseAuthentication();
app.Use(async (context, next) => {
await next();
var bearerAuth = context.Request.Headers["Authorization"]
.FirstOrDefault()?.StartsWith("Bearer ") ?? false;
if (context.Response.StatusCode == 401
&& !context.User.Identity.IsAuthenticated
&& !bearerAuth) {
await context.ChallengeAsync("oidc");
}
});
Bob 是你的叔叔...感谢这位 post 的大力帮助!! oipapio.com/question-1510997