Dotnet核心2.0认证多个模式身份cookie和jwt

时间:2017-08-20 05:09:35

标签: asp.net authentication asp.net-identity .net-core jwt

在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方法中注册   Startup.cs。 UseIdentity方法将替换为UseAuthentication。

另外还有一个参考:

  

设置默认身份验证方案

     

在1.x中,AutomaticAuthenticate和AutomaticChallenge属性   旨在设置在单一认证方案上。有   没有好办法强制执行此操作。

     

在2.0中,这两个属性已经存在   作为单个AuthenticationOptions实例上的标志删除   已经移入基础AuthenticationOptions类。属性   可以在AddAuthentication方法调用中配置   Startup.cs的ConfigureServices方法:

     

或者,使用AddAuthentication的重载版本   设置多个属性的方法。在以下重载   方法示例,默认方案设置为   CookieAuthenticationDefaults.AuthenticationScheme。身份验证   也可以在您的个人中指定方案   [授权]属性或授权策略。

在dotnet core 2.0中是否仍然可以使用多个身份验证模式?我无法获得遵守JWT配置(“承载”架构)的策略,并且目前只有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密钥设置”以获取密钥。在邮递员中,通过配置新选项卡并使用以下地址将其设置为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的回答在他的评论中涵盖了我的解决方案。我遇到的问题是在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());
    });

根据建议,这可以不使用自定义中间件。

4 个答案:

答案 0 :(得分:22)

Asp.Net Core 2.0肯定支持多种身份验证方案。 您可以尝试在Authorize属性中指定架构,而不是使用身份验证中间件进行黑客攻击:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

我试一试,它运作良好。假设您已添加Identity和JWT,如下所示:

services.AddIdentity<ApplicationUser, ApplicationRole>()
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

由于AddIdentity()已将cookie身份验证设置为默认架构,因此我们必须在控制器的Authorize属性中指定架构。目前,我不知道如何覆盖AddIdentity()设置的默认架构,或者我们最好不要这样做。

解决方法是组建一个新类(您可以称之为JwtAuthorize),该类派生自Authorize并且 Bearer 作为默认架构,因此您没有每次都指定它。

<强>更新

找到覆盖身份默认身份验证方案的方法!

而不是下线:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

使用下面的重载来设置默认架构:

services.AddAuthentication(option =>
                {
                    option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer(options =>....

更新2 如评论中所述,您可以通过将它们连接在一起来启用Identity和JWT身份验证。 [Authorize(AuthenticationSchemes = "Identity.Application" + "," + JwtBearerDefaults.AuthenticationScheme)]

答案 1 :(得分:14)

我用这个问题解决了在.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 =>....

在我基于这个问题的初始解决方案中,我没有注意到我的代码中的两个更改都是必需的。希望我可以节省一些人浪费的时间:)

答案 2 :(得分:0)

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"]))
    };

  });

答案 3 :(得分:0)

根据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帖子中提到的authorize属性中删除(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)。