首页 文章

ASP.NET Core 2.0身份验证中间件

提问于
浏览
60

随着Core 1.1遵循@ blowdart的建议并实施了一个自定义中间件:

https://stackoverflow.com/a/31465227/29821

它的工作方式如下:

  • 中间件跑了 . 从请求标头中选取一个令牌 .

  • 验证了令牌,如果有效,则构建一个包含多个声明的标识(ClaimsIdentity),然后通过HttpContext.User.AddIdentity()添加;

  • 在使用services.AddAuthorization的ConfigureServices中,我添加了一个策略来要求中间件提供的声明 .

  • 在控制器/动作中,我将使用[授权(角色= "some role that the middleware added")]

这有点适用于2.0,除了如果令牌无效(上面的步骤2)并且从未添加声明我得到“没有指定authenticationScheme,并且没有找到DefaultChallengeScheme . ”

所以现在我正在读取2.0中的auth更改:

https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x

我在ASP.NET Core 2.0中做同样事情的正确途径是什么?我没有看到做真正的自定义身份验证的示例 .

2 回答

  • 1

    因此,经过漫长的一天尝试解决这个问题之后,我终于想出了微软是如何让我们为核心2.0中的新单一中间件设置制作自定义身份验证处理程序的 .

    在查看MSDN上的一些文档后,我找到了一个名为 AuthenticationHandler<TOption> 的类,它实现了 IAuthenticationHandler 接口 .

    从那里,我找到了一个完整的代码库,其现有的身份验证方案位于https://github.com/aspnet/Security

    在其中一个内部,它显示了Microsoft如何实现JwtBearer身份验证方案 . (https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer

    我将大部分代码复制到一个新文件夹中,并清除了与 JwtBearer 有关的所有内容 .

    JwtBearerHandler 类(扩展 AuthenticationHandler<> )中,有一个 Task<AuthenticateResult> HandleAuthenticateAsync() 的覆盖

    我在旧的中间件中添加了通过自定义令牌服务器设置声明,并且仍然遇到一些权限问题,只是在令牌无效且未设置声明时吐出 200 OK 而不是 401 Unauthorized .

    我意识到我已经覆盖 Task HandleChallengeAsync(AuthenticationProperties properties) ,无论出于何种原因,它都用于通过控制器中的 [Authorize(Roles="")] 设置权限 .

    删除此覆盖后,代码已经运行,并且在权限不匹配时已成功抛出 401 .

    这里的主要内容是,现在你不能使用自定义中间件,你必须通过 AuthenticationHandler<> 来实现它,你必须在使用 services.AddAuthentication(...) 时设置 DefaultAuthenticateSchemeDefaultChallengeScheme .

    以下是这应该是什么样子的一个例子:

    在Startup.cs / ConfigureServices()中添加:

    services.AddAuthentication(options =>
    {
        // the scheme name has to match the value we're going to use in AuthenticationBuilder.AddScheme(...)
        options.DefaultAuthenticateScheme = "Custom Scheme";
        options.DefaultChallengeScheme = "Custom Scheme";
    })
    .AddCustomAuth(o => { });
    

    在Startup.cs / Configure()中添加:

    app.UseAuthentication();
    

    创建一个新文件CustomAuthExtensions.cs

    public static class CustomAuthExtensions
    {
        public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthOptions> configureOptions)
        {
            return builder.AddScheme<CustomAuthOptions, CustomAuthHandler>("Custom Scheme", "Custom Auth", configureOptions);
        }
    }
    

    创建一个新文件CustomAuthOptions.cs

    public class CustomAuthOptions: AuthenticationSchemeOptions
    {
        public CustomAuthOptions()
        {
    
        }
    }
    

    创建一个新文件CustomAuthHandler.cs

    internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions>
    {
        public CustomAuthHandler(IOptionsMonitor<CustomAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
        {
            // store custom services here...
        }
        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            // build the claims and put them in "Context"; you need to import the Microsoft.AspNetCore.Authentication package
            return AuthenticateResult.NoResult();
        }
    }
    
  • 134

    正如您所引用的文章所述,从Core 1.x到Core 2.0的身份发生了相当大的变化 . 主要的变化是远离中间件方法并使用依赖注入来配置自定义服务 . 这为定制更复杂的实现Identity提供了更大的灵活性 . 因此,您希望摆脱上面提到的中间件方法并转向服务 . 按照引用文章中的迁移步骤来实现此目标 . 首先将app.UseIdentity替换为app.UseAuthentication . UseIdentity已折旧,未来版本将不再支持 . 有关如何插入自定义声明转换并对声明view this blog post执行授权的完整示例 .

相关问题