C# ASP.NET核心2.0身份验证中间件

C# ASP.NET核心2.0身份验证中间件,c#,authentication,asp.net-core,asp.net-core-2.0,C#,Authentication,Asp.net Core,Asp.net Core 2.0,Core 1.1遵循@blowdart的建议,实现了一个自定义中间件: 它是这样工作的: 我跑了。从请求头中拾取令牌 验证令牌,如果有效,则生成包含多个声明的标识(ClaimsIdentity),然后通过HttpContext.User.AddIdentity()添加这些声明 在ConfigureServices using services.AddAuthorization中,我添加了一个策略来要求中间件提供的声明 在控制器/操作中,我将使用[Authorize(Roles=“中间件添加的某

Core 1.1遵循@blowdart的建议,实现了一个自定义中间件:

它是这样工作的:

  • 我跑了。从请求头中拾取令牌
  • 验证令牌,如果有效,则生成包含多个声明的标识(ClaimsIdentity),然后通过HttpContext.User.AddIdentity()添加这些声明
  • 在ConfigureServices using services.AddAuthorization中,我添加了一个策略来要求中间件提供的声明
  • 在控制器/操作中,我将使用[Authorize(Roles=“中间件添加的某些角色”)]
  • 这在某种程度上适用于2.0,但如果令牌无效(上面的步骤2),并且从未添加声明,我会得到“未指定authenticationScheme,并且未找到DefaultChallengeScheme”

    现在我读到2.0版本中的auth更改:


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

    正如您参考的文章所指出的,身份从Core1.x到Core2.0有很大的变化。主要的变化是不再使用中间件方法,而是使用依赖注入来配置定制服务。这为更复杂的实现定制标识提供了更大的灵活性。因此,您希望摆脱上面提到的中间件方法,转而使用服务。按照参考文章中的迁移步骤来实现这一目标。首先,将app.UseIdentity替换为app.UseAuthentication。UseIdentity已折旧,在将来的版本中将不受支持。有关如何插入自定义声明转换并对声明执行授权的完整示例,请参见。

    因此,经过一天的努力,我终于了解了Microsoft希望我们如何为core 2.0中新的单一中间件设置定制身份验证处理程序

    在浏览了一些MSDN文档之后,我发现了一个名为
    AuthenticationHandler
    的类,它实现了
    iaAuthenticationHandler
    接口

    从那里,我找到了一个完整的代码库,其中包含位于

    在其中一个示例中,它展示了Microsoft如何实现JWTBear身份验证方案。()

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

    JwtBearerHandler
    类(扩展了
    AuthenticationHandler
    )中,有一个对
    Task HandleAuthenticateAsync()

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

    我意识到我已经重写了
    Task HandleChallengeAsync(AuthenticationProperties)
    ,无论出于何种原因,它都用于通过控制器中的
    [Authorize(Roles=”“)]
    设置权限

    删除此覆盖后,代码正常工作,并且在权限不匹配时成功抛出了
    401

    这样做的主要好处是,现在您不能使用自定义中间件,您必须通过
    AuthenticationHandler
    实现它,并且必须在使用
    services.AddAuthentication(…)
    时设置
    DefaultAuthenticateScheme
    DefaultChallengeScheme

    下面是一个例子,说明这一切应该是什么样子:

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

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

    创建一个新文件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);
        }
    }
    
    创建一个新文件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();
        }
    }
    
    内部类CustomAuthHandler:AuthenticationHandler
    {
    public CustomAuthHandler(IOptionsMonitor选项、iLogger工厂记录器、UrlEncoder编码器、ISystemClock时钟):基本(选项、记录器、编码器、时钟)
    {
    //在这里存储自定义服务。。。
    }
    受保护的重写异步任务handleAuthenticateAync()
    {
    //构建声明并将其置于“上下文”中;您需要导入Microsoft.AspNetCore.Authentication包
    返回AuthenticateResult.NoResult();
    }
    }
    
    试试这个链接,尽管上面写着2个方案,但它会让你了解身份验证。你能添加你的代码让我们看看吗?我知道我在core2.0中遇到了JWT的问题-是在Startupbook中移动JWT的一个案例吗?有一个关于如何在WebAPI应用程序中使用JWT的示例吗?很好的帖子,但我在编译代码时遇到了一些问题。缺少CustomAuthOptions和AuthenticateResult类型。您可以发布这些信息吗?您是否愿意在Github回购协议的代码中分享您的结论?请您解释一下
    DefaultAuthenticateScheme
    DefaultChallengeScheme
    ?我不明白为什么两者都用?它们之间的区别是什么?+1表示“从那里,我找到了一个完整的代码库,其中包含位于的现有身份验证方案。”只需看看ASP.NET团队是如何做到这一点的,然后再给出这个(非常优秀的)答案。我们中有没有人想过,有一天我们会问一些关于MS代码和实践的问题,而答案是“看看他们的代码库?”对于稍后进来的其他人,您的
    AuthExtension
    需要位于
    Microsoft.Extensions.DependencyInjection
    命名空间中。请参见此示例:
    public static class CustomAuthExtensions
    {
        public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthOptions> configureOptions)
        {
            return builder.AddScheme<CustomAuthOptions, CustomAuthHandler>("Custom Scheme", "Custom Auth", configureOptions);
        }
    }
    
    public class CustomAuthOptions: AuthenticationSchemeOptions
    {
        public CustomAuthOptions()
        {
    
        }
    }
    
    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();
        }
    }