NET Core 2.0身份验证中间件

Core 1.1遵循了@lowdart 的建议,并实现了一个定制的中间件:

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

工作原理是这样的:

  1. 中间件运行。从请求标题中获取一个令牌。
  2. 验证了令牌,如果有效,则构建一个包含多个声明的标识(声明身份) ,然后通过 HttpContext 添加这些声明。用户。AddIdentity () ;
  3. 在 ConfigureServices using services. AddAuthorization 中,我添加了一个策略来要求由中间件提供的声明。
  4. 在控制器/操作中,我将使用[ Authorize (Roles = “ some role that the Middle ware add”)]

这在某种程度上适用于2.0,但是如果令牌无效(上面的第2步) ,并且声明从未被添加,我就会得到“没有指定认证方案,也没有找到默认挑战方案”

所以现在我正在阅读在2.0版本中修改的 auth:

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

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

70277 次浏览

There are considerable changes in Identity from Core 1.x to Core 2.0 as the article you reference points out. The major change is getting away from the middleware approach and using dependency injection to configure custom services. This provides a lot more flexibility in customizing Identity for more complex implementations. So you want to get away from the middleware approach you mention above and move towards services. Follow the migration steps in the referenced article to achieve this goal. Start by replacing app.UseIdentity with app.UseAuthentication. UseIdentity is depreciated and will not be supported in future versions. For a complete example of how to insert a custom claims transformation and perform authorization on the claim view this blog post.

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.

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

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

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)

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

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

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.

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.

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

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(...).

Here's an example of what this should all look like:

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 => { });

In Startup.cs / Configure() add:

app.UseAuthentication();

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

Create a new file CustomAuthOptions.cs

public class CustomAuthOptions: AuthenticationSchemeOptions
{
public CustomAuthOptions()
{


}
}

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