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

在ASP.NET Core 2.0中使用Facebook进行身份验证

没有身份的 ASP.NET Core 2.0 承载身份验证

如何在 ASP.NET Core 2.0 中设置多个身份验证方案?