且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-02-16 10:24:11

所以,经过一整天的努力解决这个问题后,我终于弄清楚微软希望我们如何为他们的新单机制作自定义身份验证处理程序 -核心 2.0 中的中间件设置.

So, after a long day of trying to solve this problem, I've finally figured out how Microsoft wants us to make custom authentication handlers for their new single-middleware setup in core 2.0.

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

After looking through some of the documentation on MSDN, I found a class called AuthenticationHandler<TOption> that implements the IAuthenticationHandler interface.

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

From there, I found an entire codebase with the existing authentication schemes located at https://github.com/aspnet/Security

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

Inside of one of these, it shows how Microsoft implements the JwtBearer authentication scheme. (https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer)

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

I copied most of that code over into a new folder, and cleared out all the things having to do with JwtBearer.

JwtBearerHandler 类(扩展AuthenticationHandler)中,有一个对Task的覆盖.HandleAuthenticateAsync()

In the JwtBearerHandler class (which extends AuthenticationHandler<>), there's an override for Task<AuthenticateResult> HandleAuthenticateAsync()

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

I added in our old middleware for setting up claims through a custom token server, and was still encountering some issues with permissions, just spitting out a 200 OK instead of a 401 Unauthorized when a token was invalid and no claims were set up.

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

I realized that I had overridden Task HandleChallengeAsync(AuthenticationProperties properties) which for whatever reason is used to set permissions via [Authorize(Roles="")] in a controller.

删除此覆盖后,代码有效,并在权限不匹配时成功抛出401.

After removing this override, the code had worked, and had successfully thrown a 401 when the permissions didn't match up.

主要的收获是现在你不能使用自定义中间件,你必须通过 AuthenticationHandler 来实现它,并且你必须设置 DefaultAuthenticateSchemeDefaultChallengeScheme 使用 services.AddAuthentication(...) 时.

The main takeaway from this is that now you can't use a custom middleware, you have to implement it via AuthenticationHandler<> and you have to set the DefaultAuthenticateScheme and DefaultChallengeScheme when using services.AddAuthentication(...).

下面是一个示例:

在 Startup.cs/ConfigureServices() 添加:

In Startup.cs / ConfigureServices() add:

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() 添加:

In Startup.cs / Configure() add:

app.UseAuthentication();

创建一个新文件 CustomAuthExtensions.cs

Create a new file 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

Create a new file CustomAuthOptions.cs

public class CustomAuthOptions: AuthenticationSchemeOptions
{
    public CustomAuthOptions()
    {

    }
}

新建一个文件 CustomAuthHandler.cs

Create a new file 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();
    }
}