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


89

使用Core 1.1遵循@blowdart的建议并实现了自定义中间件:

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

它像这样工作:

  1. 中间件运行了。从请求标头中提取一个令牌。
  2. 验证令牌,如果有效,则建立一个包含多个声明的身份(ClaimsIdentity),然后通过HttpContext.User.AddIdentity()添加它;
  3. 在使用services.AddAuthorization的ConfigureServices中,我添加了一个策略来要求由中间件提供的声明。
  4. 然后,在控制器/操作中,我将使用[Authorize(Roles =“中间件添加的某些角色”)]

这在2.0上适用,但是如果令牌无效(上面的步骤2)并且从不添加声明,则会得到“未指定authenticationScheme,并且未找到DefaultChallengeScheme”的信息。

所以现在我正在阅读auth在2.0中更改了:

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

在ASP.NET Core 2.0中执行相同操作的正确方法是什么?我没有看到进行真正的自定义身份验证的示例。


试试这个链接,即使它说,2种方案,但它将给ü上的身份验证抬起头wildermuth.com/2017/08/19/...
大额牛Pattankar

您可以添加代码,以便我们看看吗?我知道我在core2.0中遇到了JWT的问题-这是在创业公司中转移它的一种情况
Webezine

Answers:


193

因此,经过一整天的尝试来解决此问题,我终于弄清楚了微软希望我们如何为核心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()

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

我意识到我已经覆盖Task HandleChallengeAsync(AuthenticationProperties properties)了出于任何原因用于通过设置权限的方法[Authorize(Roles="")]在控制器中。

删除此替代之后,代码可以正常工作,并且401在权限不匹配时成功抛出了a 。

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

这是所有示例的示例:

在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();
    }
}

1
很棒的帖子,但是我在编译您的代码时遇到了一些问题。CustomAuthOptions和AuthenticateResult类型丢失。你能张贴那些吗?
alexb

8
您是否愿意在Github存储库上的代码中分享您的结论?
CSharper

2
能否请您解释DefaultAuthenticateSchemeDefaultChallengeScheme?我不明白为什么都使用它们?它们之间有什么区别。
Mohammed Noureldin

10
+1表示“从那里,我找到了一个完整的代码库,其中包含位于github.com/aspnet/Security的现有身份验证方案。” 只要看看ASP.NET团队是如何做到的,并附上这个(非常出色的)答案即可。我们中是否有人认为有一天我们会问有关MS代码和实践的问题,答案是:“看看他们的代码库”?
Marc L.

3
对于以后再来的其他人,您AuthExtension需要位于Microsoft.Extensions.DependencyInjection名称空间中。看到这个例子:github.com/aspnet/Security/blob/rel/2.0.0/src/...
加里·波利

4

正如您所引用的文章指出的那样,身份从Core 1.x到Core 2.0都有很大的变化。主要的变化是摆脱了中间件方法,并使用依赖注入来配置定制服务。这在为更复杂的实现自定义身份时提供了更大的灵活性。因此,您想摆脱上面提到的中间件方法,而转向服务。请按照参考文章中的迁移步骤来实现此目标。首先将app.UseIdentity替换为app.UseAuthenticationUseIdentity已弃用,将来的版本将不再支持。有关如何插入自定义声明转换并对声明执行授权的完整示例查看此博客文章


12
是否有关于如何将其与WebAPI应用程序一起使用的示例?
alexb
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.