ASP.NET Core 运行原理解剖[5]:Authentication

在现代应用程序中,认证已不再是简单的将用户凭证保存在浏览器中,而要适应多种场景,如App,WebAPI,第三方登录等等。在 ASP.NET 4.x 时代的Windows认证和Forms认证已无法满足现代化的需求,因此在ASP.NET Core 中对认证及授权进行了全新设计,使其更加灵活,可以应付各种场景。在上一章中,我们提到HttpContext中认证相关的功能放在了独立的模块中,以扩展的方式来展现,以保证HttpContext的简洁性,本章就来介绍一下 ASP.NET Core 认证系统的整个轮廓,以及它的切入点。

AuthenticationHttpContextExtensions

AuthenticationHttpContextExtensions 类是对 HttpContext 认证相关的扩展,它提供了如下扩展方法:

public static class AuthenticationHttpContextExtensions{   

 public static Task<AuthenticateResult> AuthenticateAsync(this HttpContext context, string scheme) =>        context.RequestServices.GetRequiredService<IAuthenticationService>().AuthenticateAsync(context, scheme);    public static Task ChallengeAsync(this HttpContext context, string scheme, AuthenticationProperties properties) { }    public static Task ForbidAsync(this HttpContext context, string scheme, AuthenticationProperties properties) { }    public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) {}    public static Task SignOutAsync(this HttpContext context, string scheme, AuthenticationProperties properties) { }    public static Task<string> GetTokenAsync(this HttpContext context, string scheme, string tokenName) { } }

主要包括如上6个扩展方法,其它的只是一些参数重载:

  • SignInAsync 用户登录成功后颁发一个证书(加密的用户凭证),用来标识用户的身份。

  • SignOutAsync 退出登录,如清除Coookie等。

  • AuthenticateAsync 验证在 SignInAsync 中颁发的证书,并返回一个 AuthenticateResult 对象,表示用户的身份。

  • ChallengeAsync 返回一个需要认证的标识来提示用户登录,通常会返回一个 401 状态码。

  • ForbidAsync 禁上访问,表示用户权限不足,通常会返回一个 403 状态码。

  • GetTokenAsync 用来获取 AuthenticationProperties 中保存的额外信息。

它们的实现都非常简单,与展示的第一个方法类似,从DI系统中获取到 IAuthenticationService 接口实例,然后调用其同名方法。

因此,如果我们希望使用认证服务,那么首先要注册 IAuthenticationService 的实例,ASP.NET Core 中也提供了对应注册扩展方法:

public static class AuthenticationCoreServiceCollectionExtensions{    public static IServiceCollection AddAuthenticationCore(this IServiceCollection services)    {
        services.TryAddScoped<IAuthenticationService, AuthenticationService>();
        services.TryAddSingleton<IClaimsTransformation, NoopClaimsTransformation>(); // Can be replaced with scoped ones that use DbContext
        services.TryAddScoped<IAuthenticationHandlerProvider, AuthenticationHandlerProvider>();
        services.TryAddSingleton<IAuthenticationSchemeProvider, AuthenticationSchemeProvider>();     
   return services;    }    
   
   public static IServiceCollection AddAuthenticationCore(this IServiceCollection services, Action<AuthenticationOptions> configureOptions)    {        services.AddAuthenticationCore();        services.Configure(configureOptions);      
     return services;    } }

如上,AddAuthenticationCore 中注册了认证系统的三大核心对象:IAuthenticationSchemeProviderIAuthenticationHandlerProvider 和 IAuthenticationService,以及一个对Claim进行转换的 IClaimsTransformation(不常用),下面就来介绍一下这三大对象。

IAuthenticationSchemeProvider

首先来解释一下 Scheme 是用来做什么的。因为在 ASP.NET Core 中可以支持各种各样的认证方式(如,cookie, bearer, oauth, openid 等等),而 Scheme 用来标识使用的是哪种认证方式,不同的认证方式其处理方式是完全不一样的,所以Scheme是非常重要的。

IAuthenticationSchemeProvider 用来提供对Scheme的注册和查询,定义如下:

public interface IAuthenticationSchemeProvider{   

 void AddScheme(AuthenticationScheme scheme);    
 Task<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync();    
 Task<AuthenticationScheme> GetSchemeAsync(string name);    
 Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync();  
 Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync();  
 Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync();    Task<AuthenticationScheme> GetDefaultForbidSchemeAsync();    Task<AuthenticationScheme> GetDefaultSignInSchemeAsync();  
 Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync(); }

其 AddScheme 方法,用来注册Scheme,而每一种Scheme最终体现为一个 AuthenticationScheme 类型的对象:

public class AuthenticationScheme{   

 public AuthenticationScheme(string name, string displayName, Type handlerType)    {      
   if (!typeof(IAuthenticationHandler).IsAssignableFrom(handlerType))        {          
    throw new ArgumentException("handlerType must implement IAuthenticationSchemeHandler.");        }        ...    }    public string Name { get; }    public string DisplayName { get; }    public Type HandlerType { get; } }

每一个Scheme中还包含一个对应的IAuthenticationHandler类型的Handler,由它来完成具体的处理逻辑,看一下它的默认实现:

public class AuthenticationSchemeProvider : IAuthenticationSchemeProvider{   
 private IDictionary<string, AuthenticationScheme> _map = new Dictionary<string, AuthenticationScheme>(StringComparer.Ordinal);  
 
   public AuthenticationSchemeProvider(IOptions<AuthenticationOptions> options)    {        _options = options.Value;    
      foreach (var builder in _options.Schemes)        {          
        var scheme = builder.Build();            AddScheme(scheme);        }    }  
   
    private Task<AuthenticationScheme> GetDefaultSchemeAsync()        => _options.DefaultScheme != null        ? GetSchemeAsync(_options.DefaultScheme)        : Task.FromResult<AuthenticationScheme>(null);    .... }

如上,通过一个内部的字典来保存我们所注册的Scheme,key为Scheme名称,然后提供一系列对该字典的查询。它还提供了一系列的GetDefaultXXXSchemeAsync方法,所使用的Key是通过构造函数中接收的AuthenticationOptions对象来获取的,如果未配置,则返回为

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值