Dotnet core 2.0 身份验证多模式身份 cookie 和 jwt
Posted
技术标签:
【中文标题】Dotnet core 2.0 身份验证多模式身份 cookie 和 jwt【英文标题】:Dotnet core 2.0 authentication multiple schemas identity cookies and jwt 【发布时间】:2018-01-28 10:34:31 【问题描述】:在 dotnet core 1.1 asp 中,我能够通过执行以下操作来配置和使用身份中间件和 jwt 中间件:
app.UseIdentity();
app.UseJwtBearerAuthentication(new JwtBearerOptions() );
这已经改变了,我们使用以下实现中间件:
app.UseAuthentication();
设置的配置是通过 Startup.cs 的 ConfigureServices 部分完成的。
迁移文档中有一些关于使用授权模式的参考:
https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x#authentication-middleware-and-services
在 2.0 项目中,身份验证是通过服务配置的。每个 身份验证方案在 ConfigureServices 方法中注册 启动.cs。 UseIdentity 方法被替换为 UseAuthentication。
另外还有一个参考:
设置默认身份验证方案
在 1.x 中,AutomaticAuthenticate 和 AutomaticChallenge 属性 旨在设置在单个身份验证方案上。有 没有很好的方法来执行这一点。
在 2.0 中,这两个属性已经 作为单个 AuthenticationOptions 实例上的标志删除,并且 已移至基本 AuthenticationOptions 类。属性 可以在 AddAuthentication 方法调用中配置 Startup.cs 的 ConfigureServices 方法:
或者,使用 AddAuthentication 的重载版本 方法来设置多个属性。在下面重载 方法示例,默认方案设置为 CookieAuthenticationDefaults.AuthenticationScheme。认证 方案也可以在您的个人中指定 [授权] 属性或授权策略。
在 dotnet core 2.0 中是否仍然可以使用多个身份验证模式?我无法获得尊重 JWT 配置(“Bearer”模式)的策略,并且目前只有 Identity 与这两个配置一起工作。我找不到多个身份验证模式的任何示例。
编辑:
我重新阅读了文档,现在明白了:
app.UseAuthentication()
添加针对默认架构的自动身份验证。 Identity 为您配置默认架构。
通过在 Startup.cs 配置中执行以下操作,我已经解决了似乎针对新 api 的黑客攻击的问题:
app.UseAuthentication();
app.Use(async (context, next) =>
if (!context.User.Identity.IsAuthenticated)
var result = await context.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
if (result?.Principal != null)
context.User = result.Principal;
await next.Invoke();
);
这是执行此操作的正确方法,还是我应该利用框架、DI 和接口来自定义 IAuthenticationSchemeProvider 的实现?
编辑 - 实现的更多细节以及在哪里可以找到它。
JWT 配置可以在这里找到,我正在使用策略来定义授权,其中包括接受的身份验证模式:
https://github.com/Arragro/ArragroCMS/blob/master/src/ArragroCMS.Management/Startup.cs
自定义中间件仍在实施。 Auth 控制器在这里:
https://github.com/Arragro/ArragroCMS/blob/master/src/ArragroCMS.Web.Management/ApiControllers/AuthController.cs
它使用应用程序生成的 API 密钥来获得对数据的只读访问权限。您可以在此处找到使用该策略的控制器的实现:
https://github.com/Arragro/ArragroCMS/blob/master/src/ArragroCMS.Web.Management/ApiControllers/SitemapController.cs
更改数据库连接字符串以指向您的 SQL Server,然后运行应用程序。它会自动迁移数据库并配置管理员用户 (support@arragro.com - ArragroPassword1!)。然后转到菜单栏中的“设置”选项卡并单击“配置 JWT ReadOnly API 密钥设置”以获取密钥。在 postman 中,通过配置新选项卡并将其设置为 POST 并使用以下地址获取 jwt 令牌:
http://localhost:5000/api/auth/readonly-token
提供标头:Content-Type: application/json
供应身体:
"apiKey": "the api token from the previous step"
复制响应中的令牌,然后在邮递员中使用以下内容:
http://localhost:5000/api/sitemap/flat
Authorization: "bearer - The token you received in the previous request"
由于自定义中间件,它最初可以工作。把上面提到的代码注释掉,再试一次,就会收到401。
编辑 -@DonnyTian 下面的回答涵盖了我在他的 cmets 中的解决方案。我遇到的问题是在 UseMvc 上设置默认策略,但不提供架构:
services.AddMvc(config =>
var defaultPolicy = new AuthorizationPolicyBuilder(new[] JwtBearerDefaults.AuthenticationScheme, IdentityConstants.ApplicationScheme )
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(defaultPolicy));
config.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
config.Filters.Add(new ValidateModelAttribute());
);
按照建议,这无需自定义中间件即可工作。
【问题讨论】:
在 ConfigureServices 中分享您的 JWT 配置代码。 此代码可在此处获得:github.com/Arragro/ArragroCMS/blob/master/src/…。当前使用自定义中间件的实现确实有效,但我更希望策略/身份验证属性上的模式实现 【参考方案1】:Asp.Net Core 2.0 绝对支持多种身份验证方案。
您可以尝试在 Authorize
属性中指定架构,而不是使用身份验证中间件进行黑客攻击:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
我试了一下,效果很好。假设您已添加 Identity 和 JWT,如下所示:
services.AddIdentity<ApplicationUser, ApplicationRole>()
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
由于AddIdentity()
已经将cookie 身份验证设置为默认模式,我们必须在控制器的Authorize
属性中指定模式。目前,我不知道如何覆盖AddIdentity()
设置的默认架构,或者我们最好不要这样做。
一种解决方法是编写一个派生自 Authorize
的新类(您可以将其称为 JwtAuthorize),并将 Bearer 作为默认架构,因此您不必每次都指定它时间。
更新
找到了覆盖 Identity 默认身份验证方案的方法!
而不是下面的行:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
使用下面的重载来设置默认架构:
services.AddAuthentication(option =>
option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
)
.AddJwtBearer(options =>....
更新 2
如 cmets 中所述,您可以通过将 Identity 和 JWT auth 连接在一起来启用它们。
[Authorize(AuthenticationSchemes = "Identity.Application" + "," + JwtBearerDefaults.AuthenticationScheme)]
【讨论】:
只是想指出一些你上面没有提到的东西。 Authorize 属性中的 AuthenticationSchemes 属性接受以逗号分隔的身份验证方案名称列表。像 [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme + "," + CookieAuthenticationDefaults.AuthenticationScheme)] 不知道为什么答案有反对票。这应该是一个有效的答案,请注意问题是关于身份和 JWT。身份框架自动为您添加 cookie。 我无法让它工作。每个请求都返回 401。我收到“用户授权失败:null”。 “过滤器'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'的请求授权失败。” “使用身份验证方案 ([]) 执行 ChallengeResult。” “AuthenticationScheme:Identity.Application 受到挑战。”。在上面的示例中,每个授权都是使用 Identity 执行的,JWT 甚至没有受到挑战。真的希望这是答案,因为它对我来说最有意义。 我查看了您的 Startup.cs 并发现了问题:line#129 services.AddAuthentication(),您应该传递一个字符串来告诉您添加的方案名称。正如我的回答所说。并且您删除该行正下方的“.AddCookie()”行,因为承载令牌不使用任何 cookie,它使用 HTTP 标头来传递令牌。 @DonnyTian,对我来说,以下已修复 [Authorize(AuthenticationSchemes = "Identity.Application" + "," + JwtBearerDefaults.AuthenticationScheme)]【参考方案2】:我使用这个问题来解决我在 .Net Core 2.0 Web 应用程序中结合身份和承载身份验证的(类似)问题。需要注意的重要一点是,您需要将new[] JwtBearerDefaults.AuthenticationScheme, IdentityConstants.ApplicationScheme
添加到以下代码中:
services.AddMvc(config =>
var defaultPolicy = new AuthorizationPolicyBuilder(new[] JwtBearerDefaults.AuthenticationScheme, IdentityConstants.ApplicationScheme )
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(defaultPolicy));
config.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
config.Filters.Add(new ValidateModelAttribute());
);
与
添加默认身份验证选项:
services.AddAuthentication(option =>
option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
)
.AddJwtBearer(options =>....
在基于这个问题的最初解决方案中,我没有注意到我的代码中需要进行这两项更改。希望我可以节省我浪费的时间:)
【讨论】:
这点真的很好。我有 IdentityServer 4 提供 JWT 令牌身份验证和常规 cookie 身份验证。但是在我将 IdentityConstants.ApplicationScheme 添加到 AddAuthenticationSchemes 之前,我的授权不起作用。我之前添加了 CookieAuthenticationDefaults.AuthenticationScheme 我猜这不是那里需要的。 哇!不是 cookie,而是身份...非常感谢!【参考方案3】:根据 kevin rich 在这里所说的 http://www.whoiskevinrich.com/configuring-asp-net-core-2-0-authentication
我能够将 jwt 设置为默认身份验证方法:
services.AddAuthentication(sharedOptions =>
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme;
)
我对此进行了测试,并能够从 donnytian 帖子中提到的授权属性中删除 (AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)。
【讨论】:
这只是摆脱了身份,只剩下 Jwt 而已。 如果您查看 donntian 的更新,您会注意到他发布了同样的内容,只是稍微简洁一些。您的编辑更正了我们对 usemvc 所需的内容。 另外,这只是覆盖默认值。如果您检查选项,身份仍然存在,以防有人想先配置 jwt,然后再配置 cookie。 是的,我完全误解了默认值,无论您的控制器上是否有授权属性,我都没有意识到它们已被应用。你是对的,这种方式会使 Jwt 成为默认的身份验证选项。【参考方案4】:Sean Wildermuth 有关于启用 cookie 和 jwt 的博文:https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2
他像这样把它锁起来:
services.AddAuthentication()
.AddCookie(cfg => cfg.SlidingExpiration = true)
.AddJwtBearer(cfg =>
cfg.RequireHttpsMetadata = false;
cfg.SaveToken = true;
cfg.TokenValidationParameters = new TokenValidationParameters()
ValidIssuer = Configuration["Tokens:Issuer"],
ValidAudience = Configuration["Tokens:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
;
);
【讨论】:
我唯一的问题是我想使用身份。这将涉及滚动不同的东西。我可以走这条路,但这不是我最初打算做的。以上是关于Dotnet core 2.0 身份验证多模式身份 cookie 和 jwt的主要内容,如果未能解决你的问题,请参考以下文章
如何在 dotnet core 中制作自定义身份验证过滤器,如 Iauthentication
DotNet Core:如何跨平台客户端证书 TLS 身份验证?
在 IdentityServer4 和 Dotnet Core Identity 中使用带有身份验证 (oidc) 的 sms otp