• asp.net core 3.0认证


    整体概况

    整个asp.net core在StartUp类的Configure方法中使用一个UseAuthentication()的方式将认证这个中间件添加到了应用中。这个中间件的源码很短,如下:

    public class AuthenticationMiddleware
      {
        private readonly RequestDelegate _next;
    
        public AuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes)
        {
          if (next == null)
            throw new ArgumentNullException(nameof (next));
          if (schemes == null)
            throw new ArgumentNullException(nameof (schemes));
          this._next = next;
          this.Schemes = schemes;
        }
    
        public IAuthenticationSchemeProvider Schemes { get; set; }
    
        public async Task Invoke(HttpContext context)
        {
          context.Features.Set<IAuthenticationFeature>((IAuthenticationFeature) new AuthenticationFeature()
          {
            OriginalPath = context.Request.Path,
            OriginalPathBase = context.Request.PathBase
          });
          IAuthenticationHandlerProvider handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
          foreach (AuthenticationScheme authenticationScheme in await this.Schemes.GetRequestHandlerSchemesAsync())//GetReRequestHandlersAsync方法返回_requestHandlers字段保存的所有远程认证的Scheme
          {
            IAuthenticationRequestHandler handlerAsync = await handlers.GetHandlerAsync(context, authenticationScheme.Name) as IAuthenticationRequestHandler;
            bool flag = handlerAsync != null;
            if (flag)
              flag = await handlerAsync.HandleRequestAsync();
            if (flag)
              return;
          }
          AuthenticationScheme authenticateSchemeAsync = await this.Schemes.GetDefaultAuthenticateSchemeAsync();
          if (authenticateSchemeAsync != null)
          {
            AuthenticateResult authenticateResult = await context.AuthenticateAsync(authenticateSchemeAsync.Name);
            if (authenticateResult?.Principal != null)
              context.User = authenticateResult.Principal;
          }
          await this._next(context);
        }
      }

    基本的流程是先找一个IAuthenticationRequestHandler,这个接口代表了远程认证,逻辑是①找到一个不为空的handler并执行HandlerRequestAsync;②如果执行结果为true,则返回,否则,继续下一个循环。如果没有找到任何IAuthenticationRequestHandler,则继续由GetDefaultAuthenticateSchemeAsync方法来找一个默认的本地认证Scheme,这个本地认证Scheme的逻辑是从AuthenticationOptions中先查看DefaultAuthenticationScheme是否有值(string),如果没有,再从DefaultScheme中查看是否有值(string)如果两者都没有,那么返回一个null。(注:认证中间件依赖一个IAuthenticationSchemeProvider(构造函数注入),后者的默认实现AuthenticationSchemeProvider依赖AuthenticationOptions类)。

    整个asp.net core 认证的线索为IAuthenticationService,这个接口声明了5个动作方法,其中,具体的执行是由IAuthenticationHandler来执行的,这个接口定义了AuthenticateAsync()、ForbiddenAsync()和ChallengeAsync()。而SignInAsync和SignOutAsync则分别由IAuthenticationSignInHandler和IAuthenticationSignOutHandler来定义的。后两个接口也继承自IAuthenticationHandler,IAuthenticationHandler由IAuthenticationHandlerProvider来提供,IAuthenticationHandlerProvider使用IAuthenticationSchemeProvider来提供一个具体的AuthenticationScheme,AuthenticationScheme代表一个具体的方案,这个Scheme中包含了执行这个方案需要的HandlerType,也即是IAuthenticationHandler,从Scheme中拿到这个HandlerType之后,从DI或者ActivityUtils中得到具体的IAuthenticaitonHandler来执行最终逻辑。其他的诸如AuthenticateResult代表一个认证验证结果,他里面维护了一个AuthenticationTicket,还有一个AuthenticateProperties表示认证的一些特征,如颁发时间、过期时间等等。

    这篇文章涉及的源码包括Microsoft.AspNETCore.Authentication.Abstraction、Microsoft.AspNETCore.Authentication.Core和Microsoft.AspNETCore.Authentication

    认证和授权很相似,他们的英文也很相似,一个是Authentication认证,一个是Authorization授权。

    asp.net core中的认证需要在Startup类中进行配置:

    //ConfigureServices方法中:
     services.AddAuthentication(option =>
                {
                    option.DefaultScheme = "Cookie";
                    option.DefaultChallengeScheme = "Cookie";
                    option.DefaultAuthenticateScheme = "Cookie";
                    option.DefaultForbidScheme = "Cookie";
                    option.DefaultSignInScheme = "Cookie";
                    option.DefaultSignOutScheme = "Cookie";
                }).AddCookie("Cookie", option =>
                {
                    option.LoginPath = "/Account/Login";
                    option.AccessDeniedPath = "/Account/Forbidden";
                    //.......
                });
    //Configure方法中
     app.UseAuthentication();

    看一看到如果需要认证的话是需要分别在ConfigureService方法和Configure方法中分别进行配置的。

    我们看到上面在AddAuthentication方法中配置了一个option,这个option是一个Action<AuthenticationOption>,在里面,写了一堆scheme。这个scheme是什么意思呢?我们先解释一下在asp.neet core中发生的这几个动作。在asp.net core中是有5个动作要发生的:

    1、登陆(Signin):用户要进行登陆的动作。

    2、登出(Signout):用户要进行登出。

    3、Challenge:这个不好翻译,意思当用户需要请求一个被保护的资源时,系统要求用户进行登陆。总之他也是一个登陆的动作,但是被动的登陆,一般返回401。

    4、Authenticate:认证,系统将用户的信息从token/cookie中读取出来。和登陆这个动作正好相反。

    5、Forbid:系统对用户执行了拒绝的操作。一般返回403

    上面这些动作最后都是由一个Handler来执行的,这个handler就是一个IAuthenticationHandler的实现。

    我们先给出了上面的总结,再看一下具体的情况。asp.net core2.0开始上面的这些动作的执行都是通过HttpContext的扩展方法来执行的。我们拿登陆来说,其他都大同小异。

    先看HttpContext.SigninAsync这个方法:

                var claim = new Claim("name", "wallee");//claim相当于我的众多信息中的一个信息单元,还有年龄、性别、家庭等等
                var identity = new ClaimsIdentity("身份证");//identity表示一个claim集合,这个集合代表了一个完整的“证件信息”,比如我的身份证
                identity.AddClaim(claim);//将上面那个信息片段添加到我的身份证里面
                var me=new ClaimsPrincipal(identity);//将身份证作为我个人的初始化参数,初始化一个ClaimsPrincipal就代表了我这个主体。还可以添加其他的identity,如还有驾驶证、准考证、会计证、计算机二级证等等
                HttpContext.SignInAsync(me);//最后,利用这个主体,调用HttpContext的扩展方法进行登陆。

    上面的代码中注释解释了一些和本文无关但又非常重要的信息,我们关键看最后哪一行:HttpContext.SigninAsync(principal);这行代码实现了最终的登陆。现在我们看一下它的实现:

    public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
        {
          return context.RequestServices.GetRequiredService<IAuthenticationService>().SignInAsync(context, scheme, principal, properties);
    }

    其实针对HttpContext的扩展方法都是调用IAuthenticationService来执行的,IAuthenticationService里面定义了针对上面描述的所有动作方法:

     1 /// <summary>Used to provide authentication.</summary>
     2   public interface IAuthenticationService
     3   {
     4     /// <summary>Authenticate for the specified authentication scheme.</summary>
     5     /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
     6     /// <param name="scheme">The name of the authentication scheme.</param>
     7     /// <returns>The result.</returns>
     8     Task<AuthenticateResult> AuthenticateAsync(
     9       HttpContext context,
    10       string scheme);
    11 
    12     /// <summary>Challenge the specified authentication scheme.</summary>
    13     /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
    14     /// <param name="scheme">The name of the authentication scheme.</param>
    15     /// <param name="properties">The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" />.</param>
    16     /// <returns>A task.</returns>
    17     Task ChallengeAsync(
    18       HttpContext context,
    19       string scheme,
    20       AuthenticationProperties properties);
    21 
    22     /// <summary>Forbids the specified authentication scheme.</summary>
    23     /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
    24     /// <param name="scheme">The name of the authentication scheme.</param>
    25     /// <param name="properties">The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" />.</param>
    26     /// <returns>A task.</returns>
    27     Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties);
    28 
    29     /// <summary>
    30     /// Sign a principal in for the specified authentication scheme.
    31     /// </summary>
    32     /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
    33     /// <param name="scheme">The name of the authentication scheme.</param>
    34     /// <param name="principal">The <see cref="T:System.Security.Claims.ClaimsPrincipal" /> to sign in.</param>
    35     /// <param name="properties">The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" />.</param>
    36     /// <returns>A task.</returns>
    37     Task SignInAsync(
    38       HttpContext context,
    39       string scheme,
    40       ClaimsPrincipal principal,
    41       AuthenticationProperties properties);
    42 
    43     /// <summary>Sign out the specified authentication scheme.</summary>
    44     /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
    45     /// <param name="scheme">The name of the authentication scheme.</param>
    46     /// <param name="properties">The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" />.</param>
    47     /// <returns>A task.</returns>
    48     Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties);
    49   }
    View Code

    IAuthenticateService在services.AddAuthentication()方法中以scoped的生命周期被注入到了DI,表示针对每次请求的新的实例。同时还被注入的有另外几个比较关键的接口:

    services.TryAddSingleton<IClaimsTransformation, NoopClaimsTransformation>();//ClaimsTransFormation用来在全局将ClaimsPrincipal添加一些新的Claims,默认注入的这个是啥都没干
    services.TryAddScoped<IAuthenticationHandlerProvider, AuthenticationHandlerProvider>();//AuthenticationHandler的提供者,提供执行Authenticatoin、Forbidden和Challenge等动作的handler
    services.TryAddSingleton<IAuthenticationSchemeProvider, AuthenticationSchemeProvider>();//AuthenticationScheme的提供者,AuthenticationScheme是对AuthenticationHandler的描述,通过Scheme找到相应的Handler

    IAuthenticationService是对IAuthenticationSchemeProvider和IAuthenticationHandlerProvider的封装,它有一个AuthenticationService的实现:

      1 /// <summary>
      2   /// Implements <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationService" />.
      3   /// </summary>
      4   public class AuthenticationService : IAuthenticationService
      5   {
      6     /// <summary>Constructor.</summary>
      7     /// <param name="schemes">The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider" />.</param>
      8     /// <param name="handlers">The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationRequestHandler" />.</param>
      9     /// <param name="transform">The <see cref="T:Microsoft.AspNetCore.Authentication.IClaimsTransformation" />.</param>
     10     public AuthenticationService(
     11       IAuthenticationSchemeProvider schemes,
     12       IAuthenticationHandlerProvider handlers,
     13       IClaimsTransformation transform)
     14     {
     15       this.Schemes = schemes;
     16       this.Handlers = handlers;
     17       this.Transform = transform;
     18     }
     19 
     20     /// <summary>Used to lookup AuthenticationSchemes.</summary>
     21     public IAuthenticationSchemeProvider Schemes { get; }
     22 
     23     /// <summary>Used to resolve IAuthenticationHandler instances.</summary>
     24     public IAuthenticationHandlerProvider Handlers { get; }
     25 
     26     /// <summary>Used for claims transformation.</summary>
     27     public IClaimsTransformation Transform { get; }
     28 
     29     /// <summary>Authenticate for the specified authentication scheme.</summary>
     30     /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
     31     /// <param name="scheme">The name of the authentication scheme.</param>
     32     /// <returns>The result.</returns>
     33     public virtual async Task<AuthenticateResult> AuthenticateAsync(
     34       HttpContext context,
     35       string scheme)
     36     {
     37       if (scheme == null)
     38       {
     39         scheme = (await this.Schemes.GetDefaultAuthenticateSchemeAsync())?.Name;
     40         if (scheme == null)
     41           throw new InvalidOperationException("No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found.");
     42       }
     43       IAuthenticationHandler handlerAsync = await this.Handlers.GetHandlerAsync(context, scheme);
     44       if (handlerAsync == null)
     45         throw await this.CreateMissingHandlerException(scheme);
     46       AuthenticateResult result = await handlerAsync.AuthenticateAsync();
     47       return result != null && result.Succeeded ? AuthenticateResult.Success(new AuthenticationTicket(await this.Transform.TransformAsync(result.Principal), result.Properties, result.Ticket.AuthenticationScheme)) : result;
     48     }
     49 
     50     /// <summary>Challenge the specified authentication scheme.</summary>
     51     /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
     52     /// <param name="scheme">The name of the authentication scheme.</param>
     53     /// <param name="properties">The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" />.</param>
     54     /// <returns>A task.</returns>
     55     public virtual async Task ChallengeAsync(
     56       HttpContext context,
     57       string scheme,
     58       AuthenticationProperties properties)
     59     {
     60       if (scheme == null)
     61       {
     62         scheme = (await this.Schemes.GetDefaultChallengeSchemeAsync())?.Name;
     63         if (scheme == null)
     64           throw new InvalidOperationException("No authenticationScheme was specified, and there was no DefaultChallengeScheme found.");
     65       }
     66       IAuthenticationHandler handlerAsync = await this.Handlers.GetHandlerAsync(context, scheme);
     67       if (handlerAsync == null)
     68         throw await this.CreateMissingHandlerException(scheme);
     69       await handlerAsync.ChallengeAsync(properties);
     70     }
     71 
     72     /// <summary>Forbid the specified authentication scheme.</summary>
     73     /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
     74     /// <param name="scheme">The name of the authentication scheme.</param>
     75     /// <param name="properties">The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" />.</param>
     76     /// <returns>A task.</returns>
     77     public virtual async Task ForbidAsync(
     78       HttpContext context,
     79       string scheme,
     80       AuthenticationProperties properties)
     81     {
     82       if (scheme == null)
     83       {
     84         scheme = (await this.Schemes.GetDefaultForbidSchemeAsync())?.Name;
     85         if (scheme == null)
     86           throw new InvalidOperationException("No authenticationScheme was specified, and there was no DefaultForbidScheme found.");
     87       }
     88       IAuthenticationHandler handlerAsync = await this.Handlers.GetHandlerAsync(context, scheme);
     89       if (handlerAsync == null)
     90         throw await this.CreateMissingHandlerException(scheme);
     91       await handlerAsync.ForbidAsync(properties);
     92     }
     93 
     94     /// <summary>
     95     /// Sign a principal in for the specified authentication scheme.
     96     /// </summary>
     97     /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
     98     /// <param name="scheme">The name of the authentication scheme.</param>
     99     /// <param name="principal">The <see cref="T:System.Security.Claims.ClaimsPrincipal" /> to sign in.</param>
    100     /// <param name="properties">The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" />.</param>
    101     /// <returns>A task.</returns>
    102     public virtual async Task SignInAsync(
    103       HttpContext context,
    104       string scheme,
    105       ClaimsPrincipal principal,
    106       AuthenticationProperties properties)
    107     {
    108       if (principal == null)
    109         throw new ArgumentNullException(nameof (principal));
    110       if (scheme == null)
    111       {
    112         scheme = (await this.Schemes.GetDefaultSignInSchemeAsync())?.Name;
    113         if (scheme == null)
    114           throw new InvalidOperationException("No authenticationScheme was specified, and there was no DefaultSignInScheme found.");
    115       }
    116       IAuthenticationHandler handlerAsync = await this.Handlers.GetHandlerAsync(context, scheme);
    117       if (handlerAsync == null)
    118         throw await this.CreateMissingSignInHandlerException(scheme);
    119       if (!(handlerAsync is IAuthenticationSignInHandler authenticationSignInHandler))
    120         throw await this.CreateMismatchedSignInHandlerException(scheme, handlerAsync);
    121       await authenticationSignInHandler.SignInAsync(principal, properties);
    122     }
    123 
    124     /// <summary>Sign out the specified authentication scheme.</summary>
    125     /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
    126     /// <param name="scheme">The name of the authentication scheme.</param>
    127     /// <param name="properties">The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" />.</param>
    128     /// <returns>A task.</returns>
    129     public virtual async Task SignOutAsync(
    130       HttpContext context,
    131       string scheme,
    132       AuthenticationProperties properties)
    133     {
    134       if (scheme == null)
    135       {
    136         scheme = (await this.Schemes.GetDefaultSignOutSchemeAsync())?.Name;
    137         if (scheme == null)
    138           throw new InvalidOperationException("No authenticationScheme was specified, and there was no DefaultSignOutScheme found.");
    139       }
    140       IAuthenticationHandler handlerAsync = await this.Handlers.GetHandlerAsync(context, scheme);
    141       if (handlerAsync == null)
    142         throw await this.CreateMissingSignOutHandlerException(scheme);
    143       if (!(handlerAsync is IAuthenticationSignOutHandler authenticationSignOutHandler))
    144         throw await this.CreateMismatchedSignOutHandlerException(scheme, handlerAsync);
    145       await authenticationSignOutHandler.SignOutAsync(properties);
    146     }
    147 
    148     private async Task<Exception> CreateMissingHandlerException(string scheme)
    149     {
    150       string str1 = string.Join(", ", (await this.Schemes.GetAllSchemesAsync()).Select<AuthenticationScheme, string>((Func<AuthenticationScheme, string>) (sch => sch.Name)));
    151       string str2 = string.Format(" Did you forget to call AddAuthentication().Add[SomeAuthHandler]("{0}",...)?", (object) scheme);
    152       return !string.IsNullOrEmpty(str1) ? (Exception) new InvalidOperationException(string.Format("No authentication handler is registered for the scheme '{0}'. The registered schemes are: {1}.", (object) scheme, (object) str1) + str2) : (Exception) new InvalidOperationException("No authentication handlers are registered." + str2);
    153     }
    154 
    155     private async Task<string> GetAllSignInSchemeNames()
    156     {
    157       return string.Join(", ", (await this.Schemes.GetAllSchemesAsync()).Where<AuthenticationScheme>((Func<AuthenticationScheme, bool>) (sch => typeof (IAuthenticationSignInHandler).IsAssignableFrom(sch.HandlerType))).Select<AuthenticationScheme, string>((Func<AuthenticationScheme, string>) (sch => sch.Name)));
    158     }
    159 
    160     private async Task<Exception> CreateMissingSignInHandlerException(string scheme)
    161     {
    162       string signInSchemeNames = await this.GetAllSignInSchemeNames();
    163       string str = string.Format(" Did you forget to call AddAuthentication().AddCookies("{0}",...)?", (object) scheme);
    164       return !string.IsNullOrEmpty(signInSchemeNames) ? (Exception) new InvalidOperationException(string.Format("No sign-in authentication handler is registered for the scheme '{0}'. The registered sign-in schemes are: {1}.", (object) scheme, (object) signInSchemeNames) + str) : (Exception) new InvalidOperationException("No sign-in authentication handlers are registered." + str);
    165     }
    166 
    167     private async Task<Exception> CreateMismatchedSignInHandlerException(
    168       string scheme,
    169       IAuthenticationHandler handler)
    170     {
    171       string signInSchemeNames = await this.GetAllSignInSchemeNames();
    172       string str = string.Format("The authentication handler registered for scheme '{0}' is '{1}' which cannot be used for SignInAsync. ", (object) scheme, (object) handler.GetType().Name);
    173       return !string.IsNullOrEmpty(signInSchemeNames) ? (Exception) new InvalidOperationException(str + string.Format("The registered sign-in schemes are: {0}.", (object) signInSchemeNames)) : (Exception) new InvalidOperationException(str + "Did you forget to call AddAuthentication().AddCookies("Cookies") and SignInAsync("Cookies",...)?");
    174     }
    175 
    176     private async Task<string> GetAllSignOutSchemeNames()
    177     {
    178       return string.Join(", ", (await this.Schemes.GetAllSchemesAsync()).Where<AuthenticationScheme>((Func<AuthenticationScheme, bool>) (sch => typeof (IAuthenticationSignOutHandler).IsAssignableFrom(sch.HandlerType))).Select<AuthenticationScheme, string>((Func<AuthenticationScheme, string>) (sch => sch.Name)));
    179     }
    180 
    181     private async Task<Exception> CreateMissingSignOutHandlerException(string scheme)
    182     {
    183       string signOutSchemeNames = await this.GetAllSignOutSchemeNames();
    184       string str = string.Format(" Did you forget to call AddAuthentication().AddCookies("{0}",...)?", (object) scheme);
    185       return !string.IsNullOrEmpty(signOutSchemeNames) ? (Exception) new InvalidOperationException(string.Format("No sign-out authentication handler is registered for the scheme '{0}'. The registered sign-out schemes are: {1}.", (object) scheme, (object) signOutSchemeNames) + str) : (Exception) new InvalidOperationException("No sign-out authentication handlers are registered." + str);
    186     }
    187 
    188     private async Task<Exception> CreateMismatchedSignOutHandlerException(
    189       string scheme,
    190       IAuthenticationHandler handler)
    191     {
    192       string signOutSchemeNames = await this.GetAllSignOutSchemeNames();
    193       string str = string.Format("The authentication handler registered for scheme '{0}' is '{1}' which cannot be used for {2}. ", (object) scheme, (object) handler.GetType().Name, (object) "SignOutAsync");
    194       return !string.IsNullOrEmpty(signOutSchemeNames) ? (Exception) new InvalidOperationException(str + string.Format("The registered sign-out schemes are: {0}.", (object) signOutSchemeNames)) : (Exception) new InvalidOperationException(str + string.Format("Did you forget to call AddAuthentication().AddCookies("Cookies") and {0}("Cookies",...)?", (object) "SignOutAsync"));
    195     }
    196   }
    View Code

    这个基本就是asp.net core 认证的整体概况了,先看一下整体的逻辑,在下一部分,我们再把一些相关的类型做一些补充说明。

    可以看到AuthenticationService里面定义的这些AuthenticationAsync、ForbiddenAsync等等动作方法基本都遵循了一个逻辑:

    ①首先判断传入的scheme是否为null,如果为null,那么根据IAuthenticationSchemeProvider类型的Schemes属性来找出一个默认的scheme,如果上述两个都失败,则抛出异常。

    ②第一步成功的前提下,利用IAuthenticationHandlerProvider类型的Handlers属性根据找出的scheme来生成一个handler。

    ③在AuthenticationAsync、ForbiddenAsync和ChallengeAsync方法中,直接调用生成的handler的同名方法来执行最终的逻辑,而在SignInAsync和SignOutAsync中要判断拿到的这个Handler是否分别实现了IAuthenticationSignInHandler和IAuthenticationSignOutHandler这两个接口,如果没有实现,则爆出异常。

    至于SignIn和SignOut这两个接口从IAuthenticatoinHandler中剥离出去是因为IAuthenticationHandler只是实现了对用户凭证的验证,至于SignIn和SignOut,现在大多数应用使用的登录方式都有所不同,况且这两个功能实现的是凭证的获取/发放,放在IAuthenticationHandler不合适。

    public interface IAuthenticationSignInHandler : IAuthenticationSignOutHandler, IAuthenticationHandler
      {
        /// <summary>Handle sign in.</summary>
        /// <param name="user">The <see cref="T:System.Security.Claims.ClaimsPrincipal" /> user.</param>
        /// <param name="properties">The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" /> that contains the extra meta-data arriving with the authentication.</param>
        /// <returns>A task.</returns>
        Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties);
      }
    public interface IAuthenticationSignOutHandler : IAuthenticationHandler
      {
        /// <summary>Signout behavior.</summary>
        /// <param name="properties">The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" /> that contains the extra meta-data arriving with the authentication.</param>
        /// <returns>A task.</returns>
        Task SignOutAsync(AuthenticationProperties properties);
      }

    关键类型

    AuthenticationScheme

     1 public class AuthenticationScheme
     2   {
     3     /// <summary>Constructor.</summary>
     4     /// <param name="name">The name for the authentication scheme.</param>
     5     /// <param name="displayName">The display name for the authentication scheme.</param>
     6     /// <param name="handlerType">The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationHandler" /> type that handles this scheme.</param>
     7     public AuthenticationScheme(string name, string displayName, Type handlerType)
     8     {
     9       if (name == null)
    10         throw new ArgumentNullException(nameof (name));
    11       if (handlerType == (Type) null)
    12         throw new ArgumentNullException(nameof (handlerType));
    13       if (!typeof (IAuthenticationHandler).IsAssignableFrom(handlerType))
    14         throw new ArgumentException("handlerType must implement IAuthenticationHandler.");
    15       this.Name = name;
    16       this.HandlerType = handlerType;
    17       this.DisplayName = displayName;
    18     }
    19 
    20     /// <summary>The name of the authentication scheme.</summary>
    21     public string Name { get; }
    22 
    23     /// <summary>
    24     /// The display name for the scheme. Null is valid and used for non user facing schemes.
    25     /// </summary>
    26     public string DisplayName { get; }
    27 
    28     /// <summary>
    29     /// The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationHandler" /> type that handles this scheme.
    30     /// </summary>
    31     public Type HandlerType { get; }
    32   }
    View Code

    一个AuthenticationScheme就是一个对IAuthenticationHandler的描述,它为一个特定的handlerType分配了一个名称(name)。它的构造函数接收三个参数了分别初始化了内部的三个属性,并对这三个参数做了严格的校验保证输入的参数有效。

    AuthenticationSchemeBuilder

     1 public class AuthenticationSchemeBuilder
     2   {
     3     /// <summary>Constructor.</summary>
     4     /// <param name="name">The name of the scheme being built.</param>
     5     public AuthenticationSchemeBuilder(string name)
     6     {
     7       this.Name = name;
     8     }
     9 
    10     /// <summary>The name of the scheme being built.</summary>
    11     public string Name { get; }
    12 
    13     /// <summary>The display name for the scheme being built.</summary>
    14     public string DisplayName { get; set; }
    15 
    16     /// <summary>
    17     /// The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationHandler" /> type responsible for this scheme.
    18     /// </summary>
    19     public Type HandlerType { get; set; }
    20 
    21     /// <summary>
    22     /// Builds the <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationScheme" /> instance.
    23     /// </summary>
    24     /// <returns></returns>
    25     public AuthenticationScheme Build()
    26     {
    27       return new AuthenticationScheme(this.Name, this.DisplayName, this.HandlerType);
    28     }
    29   }
    View Code

    从名字就能看出来它是AuthenticationScheme的建造者,它内部包含的三个属性和AuthenticationScheme是一样的。它的构造函数需要一个string类型的name参数来初始化name,没有对输入的参数做任何校验,另外毫无意外的它有一个Build方法,用自身的这三个属性来new一个AuthenticationScheme。

    AutenticaitonOptions

     1 public class AuthenticationOptions
     2   {
     3     private readonly IList<AuthenticationSchemeBuilder> _schemes = (IList<AuthenticationSchemeBuilder>) new List<AuthenticationSchemeBuilder>();
     4 
     5     /// <summary>
     6     /// Returns the schemes in the order they were added (important for request handling priority)
     7     /// </summary>
     8     public IEnumerable<AuthenticationSchemeBuilder> Schemes
     9     {
    10       get
    11       {
    12         return (IEnumerable<AuthenticationSchemeBuilder>) this._schemes;
    13       }
    14     }
    15 
    16     /// <summary>Maps schemes by name.</summary>
    17     public IDictionary<string, AuthenticationSchemeBuilder> SchemeMap { get; } = (IDictionary<string, AuthenticationSchemeBuilder>) new Dictionary<string, AuthenticationSchemeBuilder>((IEqualityComparer<string>) StringComparer.Ordinal);
    18 
    19     /// <summary>
    20     /// Adds an <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationScheme" />.
    21     /// </summary>
    22     /// <param name="name">The name of the scheme being added.</param>
    23     /// <param name="configureBuilder">Configures the scheme.</param>
    24     public void AddScheme(
    25       string name,
    26       Action<AuthenticationSchemeBuilder> configureBuilder)
    27     {
    28       if (name == null)
    29         throw new ArgumentNullException(nameof (name));
    30       if (configureBuilder == null)
    31         throw new ArgumentNullException(nameof (configureBuilder));
    32       if (this.SchemeMap.ContainsKey(name))
    33         throw new InvalidOperationException("Scheme already exists: " + name);
    34       AuthenticationSchemeBuilder authenticationSchemeBuilder = new AuthenticationSchemeBuilder(name);
    35       configureBuilder(authenticationSchemeBuilder);
    36       this._schemes.Add(authenticationSchemeBuilder);
    37       this.SchemeMap[name] = authenticationSchemeBuilder;
    38     }
    39 
    40     /// <summary>
    41     /// Adds an <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationScheme" />.
    42     /// </summary>
    43     /// <typeparam name="THandler">The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationHandler" /> responsible for the scheme.</typeparam>
    44     /// <param name="name">The name of the scheme being added.</param>
    45     /// <param name="displayName">The display name for the scheme.</param>
    46     public void AddScheme<THandler>(string name, string displayName) where THandler : IAuthenticationHandler
    47     {
    48       this.AddScheme(name, (Action<AuthenticationSchemeBuilder>) (b =>
    49       {
    50         b.DisplayName = displayName;
    51         b.HandlerType = typeof (THandler);
    52       }));
    53     }
    54 
    55     /// <summary>
    56     /// Used as the fallback default scheme for all the other defaults.
    57     /// </summary>
    58     public string DefaultScheme { get; set; }
    59 
    60     /// <summary>
    61     /// Used as the default scheme by <see cref="M:Microsoft.AspNetCore.Authentication.IAuthenticationService.AuthenticateAsync(Microsoft.AspNetCore.Http.HttpContext,System.String)" />.
    62     /// </summary>
    63     public string DefaultAuthenticateScheme { get; set; }
    64 
    65     /// <summary>
    66     /// Used as the default scheme by <see cref="M:Microsoft.AspNetCore.Authentication.IAuthenticationService.SignInAsync(Microsoft.AspNetCore.Http.HttpContext,System.String,System.Security.Claims.ClaimsPrincipal,Microsoft.AspNetCore.Authentication.AuthenticationProperties)" />.
    67     /// </summary>
    68     public string DefaultSignInScheme { get; set; }
    69 
    70     /// <summary>
    71     /// Used as the default scheme by <see cref="M:Microsoft.AspNetCore.Authentication.IAuthenticationService.SignOutAsync(Microsoft.AspNetCore.Http.HttpContext,System.String,Microsoft.AspNetCore.Authentication.AuthenticationProperties)" />.
    72     /// </summary>
    73     public string DefaultSignOutScheme { get; set; }
    74 
    75     /// <summary>
    76     /// Used as the default scheme by <see cref="M:Microsoft.AspNetCore.Authentication.IAuthenticationService.ChallengeAsync(Microsoft.AspNetCore.Http.HttpContext,System.String,Microsoft.AspNetCore.Authentication.AuthenticationProperties)" />.
    77     /// </summary>
    78     public string DefaultChallengeScheme { get; set; }
    79 
    80     /// <summary>
    81     /// Used as the default scheme by <see cref="M:Microsoft.AspNetCore.Authentication.IAuthenticationService.ForbidAsync(Microsoft.AspNetCore.Http.HttpContext,System.String,Microsoft.AspNetCore.Authentication.AuthenticationProperties)" />.
    82     /// </summary>
    83     public string DefaultForbidScheme { get; set; }
    84   }
    View Code

    这个类为添加Scheme提供了便利,它维护了一个AuthenticationSchemeBuilder的列表和一个同类型的字典。------------------------

    IAuthenticationHandlerProvider

    public interface IAuthenticationHandlerProvider 
    { 
    Task<IAuthenticationHandler> GetHandlerAsync(HttpContext context, string authenticationScheme);
    }

    IAuthenticationHandler负责对用户的凭证进行校验,而这个Provider就是用来提供一个IAuthenticationHandler,它只有一个方法就是GetHandlerAsync(HttpContext context,string authenticationScheme)。从方法的参数传入也能知道IAuthenticationHnadlerProvider的实现依赖于AuthenticationScheme,确实,它的实现AuthenticationHandlerProvider里面确实维护了一个IAuthenticationSchemeProvider:

     1 public class AuthenticationHandlerProvider : IAuthenticationHandlerProvider
     2   {
     3     private Dictionary<string, IAuthenticationHandler> _handlerMap = new Dictionary<string, IAuthenticationHandler>((IEqualityComparer<string>) StringComparer.Ordinal);
     4 
     5     /// <summary>Constructor.</summary>
     6     /// <param name="schemes">The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationHandlerProvider" />.</param>
     7     public AuthenticationHandlerProvider(IAuthenticationSchemeProvider schemes)
     8     {
     9       this.Schemes = schemes;
    10     }
    11 
    12     /// <summary>
    13     /// The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationHandlerProvider" />.
    14     /// </summary>
    15     public IAuthenticationSchemeProvider Schemes { get; }
    16 
    17     /// <summary>Returns the handler instance that will be used.</summary>
    18     /// <param name="context">The context.</param>
    19     /// <param name="authenticationScheme">The name of the authentication scheme being handled.</param>
    20     /// <returns>The handler instance.</returns>
    21     public async Task<IAuthenticationHandler> GetHandlerAsync(
    22       HttpContext context,
    23       string authenticationScheme)
    24     {
    25       if (this._handlerMap.ContainsKey(authenticationScheme))
    26         return this._handlerMap[authenticationScheme];
    27       AuthenticationScheme schemeAsync = await this.Schemes.GetSchemeAsync(authenticationScheme);
    28       if (schemeAsync == null)
    29         return (IAuthenticationHandler) null;
    30       if ((context.RequestServices.GetService(schemeAsync.HandlerType) ?? ActivatorUtilities.CreateInstance(context.RequestServices, schemeAsync.HandlerType)) is IAuthenticationHandler handler)
    31       {
    32         await handler.InitializeAsync(schemeAsync, context);
    33         this._handlerMap[authenticationScheme] = handler;
    34       }
    35       return handler;
    36     }
    37   }
    View Code

    IAuthenticationHandlerProvider的目的很明确,就是要提供一个IAuthenticationHandler,它的逻辑如下:

    ①首先根据authenticationScheme查看_handlerMap是否包含相应的handler如果包含直接返回这个handler。

    ②如果没有从第一步中找到,那么就从Schemes属性中根据authenticationScheme找出相应的AuthenticationScheme,如果这个Scheme为空,那么直接返回一个null。

    ③如果从Schemes属性中找出的AuthenticationScheme不为空,那么或者从传入的HttpContext类型的context.RequestServices.GetService方法中找Handler,或者使用ActivatorUtilities来创建一个,不管使用那种方式都是从拿到的scheme中记录的handlerType来获取handler的。如果是一个IAuthenticationHandler,那么调用handler. InitializeAsync方法(注一)来初始化本身,并将这个handler放入自身的_handlerMap字典中。最后将这个handler返回。

    AuthenticateResult

      1 public class AuthenticateResult
      2   {
      3     protected AuthenticateResult()
      4     {
      5     }
      6 
      7     /// <summary>
      8     /// If a ticket was produced, authenticate was successful.
      9     /// </summary>
     10     public bool Succeeded
     11     {
     12       get
     13       {
     14         return this.Ticket != null;
     15       }
     16     }
     17 
     18     /// <summary>The authentication ticket.</summary>
     19     public AuthenticationTicket Ticket { get; protected set; }
     20 
     21     /// <summary>
     22     /// Gets the claims-principal with authenticated user identities.
     23     /// </summary>
     24     public ClaimsPrincipal Principal
     25     {
     26       get
     27       {
     28         return this.Ticket?.Principal;
     29       }
     30     }
     31 
     32     /// <summary>
     33     /// Additional state values for the authentication session.
     34     /// </summary>
     35     public AuthenticationProperties Properties { get; protected set; }
     36 
     37     /// <summary>Holds failure information from the authentication.</summary>
     38     public Exception Failure { get; protected set; }
     39 
     40     /// <summary>
     41     /// Indicates that there was no information returned for this authentication scheme.
     42     /// </summary>
     43     public bool None { get; protected set; }
     44 
     45     /// <summary>Indicates that authentication was successful.</summary>
     46     /// <param name="ticket">The ticket representing the authentication result.</param>
     47     /// <returns>The result.</returns>
     48     public static AuthenticateResult Success(AuthenticationTicket ticket)
     49     {
     50       if (ticket == null)
     51         throw new ArgumentNullException(nameof (ticket));
     52       return new AuthenticateResult()
     53       {
     54         Ticket = ticket,
     55         Properties = ticket.Properties
     56       };
     57     }
     58 
     59     /// <summary>
     60     /// Indicates that there was no information returned for this authentication scheme.
     61     /// </summary>
     62     /// <returns>The result.</returns>
     63     public static AuthenticateResult NoResult()
     64     {
     65       return new AuthenticateResult() { None = true };
     66     }
     67 
     68     /// <summary>
     69     /// Indicates that there was a failure during authentication.
     70     /// </summary>
     71     /// <param name="failure">The failure exception.</param>
     72     /// <returns>The result.</returns>
     73     public static AuthenticateResult Fail(Exception failure)
     74     {
     75       return new AuthenticateResult() { Failure = failure };
     76     }
     77 
     78     /// <summary>
     79     /// Indicates that there was a failure during authentication.
     80     /// </summary>
     81     /// <param name="failure">The failure exception.</param>
     82     /// <param name="properties">Additional state values for the authentication session.</param>
     83     /// <returns>The result.</returns>
     84     public static AuthenticateResult Fail(
     85       Exception failure,
     86       AuthenticationProperties properties)
     87     {
     88       return new AuthenticateResult()
     89       {
     90         Failure = failure,
     91         Properties = properties
     92       };
     93     }
     94 
     95     /// <summary>
     96     /// Indicates that there was a failure during authentication.
     97     /// </summary>
     98     /// <param name="failureMessage">The failure message.</param>
     99     /// <returns>The result.</returns>
    100     public static AuthenticateResult Fail(string failureMessage)
    101     {
    102       return AuthenticateResult.Fail(new Exception(failureMessage));
    103     }
    104 
    105     /// <summary>
    106     /// Indicates that there was a failure during authentication.
    107     /// </summary>
    108     /// <param name="failureMessage">The failure message.</param>
    109     /// <param name="properties">Additional state values for the authentication session.</param>
    110     /// <returns>The result.</returns>
    111     public static AuthenticateResult Fail(
    112       string failureMessage,
    113       AuthenticationProperties properties)
    114     {
    115       return AuthenticateResult.Fail(new Exception(failureMessage), properties);
    116     }
    117   }
    View Code

    一个认证结果,表示AuthenticationService中的方法返回的结果。典型的状态模式。它内部维护一个AuthenticationTicket。可直接调用Success方法或这Fail方法来返回包含相应状态的Result。

    AuthenticatoinTicket

     1 public class AuthenticationTicket
     2   {
     3     /// <summary>
     4     /// Initializes a new instance of the <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationTicket" /> class
     5     /// </summary>
     6     /// <param name="principal">the <see cref="T:System.Security.Claims.ClaimsPrincipal" /> that represents the authenticated user.</param>
     7     /// <param name="properties">additional properties that can be consumed by the user or runtime.</param>
     8     /// <param name="authenticationScheme">the authentication middleware that was responsible for this ticket.</param>
     9     public AuthenticationTicket(
    10       ClaimsPrincipal principal,
    11       AuthenticationProperties properties,
    12       string authenticationScheme)
    13     {
    14       if (principal == null)
    15         throw new ArgumentNullException(nameof (principal));
    16       this.AuthenticationScheme = authenticationScheme;
    17       this.Principal = principal;
    18       this.Properties = properties ?? new AuthenticationProperties();
    19     }
    20 
    21     /// <summary>
    22     /// Initializes a new instance of the <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationTicket" /> class
    23     /// </summary>
    24     /// <param name="principal">the <see cref="T:System.Security.Claims.ClaimsPrincipal" /> that represents the authenticated user.</param>
    25     /// <param name="authenticationScheme">the authentication middleware that was responsible for this ticket.</param>
    26     public AuthenticationTicket(ClaimsPrincipal principal, string authenticationScheme)
    27       : this(principal, (AuthenticationProperties) null, authenticationScheme)
    28     {
    29     }
    30 
    31     /// <summary>Gets the authentication type.</summary>
    32     public string AuthenticationScheme { get; private set; }
    33 
    34     /// <summary>
    35     /// Gets the claims-principal with authenticated user identities.
    36     /// </summary>
    37     public ClaimsPrincipal Principal { get; private set; }
    38 
    39     /// <summary>
    40     /// Additional state values for the authentication session.
    41     /// </summary>
    42     public AuthenticationProperties Properties { get; private set; }
    43   }
    View Code

    表示一个经过认证后颁发的证书,里面包含ClaimsPrincipal、AuthenticationScheme和AuthenticationProperties三个属性,ClaimsPrincipal表示证书的主体,如姓名、电话等等信息,AuthenticationProperties表示证书的相关信息,如颁发时间、过期时间和重定向地址等等。

    AuthenticationProperties

      1  public class AuthenticationProperties
      2   {
      3     internal const string IssuedUtcKey = ".issued";
      4     internal const string ExpiresUtcKey = ".expires";
      5     internal const string IsPersistentKey = ".persistent";
      6     internal const string RedirectUriKey = ".redirect";
      7     internal const string RefreshKey = ".refresh";
      8     internal const string UtcDateTimeFormat = "r";
      9 
     10     /// <summary>
     11     /// Initializes a new instance of the <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" /> class.
     12     /// </summary>
     13     public AuthenticationProperties()
     14       : this((IDictionary<string, string>) null, (IDictionary<string, object>) null)
     15     {
     16     }
     17 
     18     /// <summary>
     19     /// Initializes a new instance of the <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" /> class.
     20     /// </summary>
     21     /// <param name="items">State values dictionary to use.</param>
     22     public AuthenticationProperties(IDictionary<string, string> items)
     23       : this(items, (IDictionary<string, object>) null)
     24     {
     25     }
     26 
     27     /// <summary>
     28     /// Initializes a new instance of the <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationProperties" /> class.
     29     /// </summary>
     30     /// <param name="items">State values dictionary to use.</param>
     31     /// <param name="parameters">Parameters dictionary to use.</param>
     32     public AuthenticationProperties(
     33       IDictionary<string, string> items,
     34       IDictionary<string, object> parameters)
     35     {
     36       this.Items = items ?? (IDictionary<string, string>) new Dictionary<string, string>((IEqualityComparer<string>) StringComparer.Ordinal);
     37       this.Parameters = parameters ?? (IDictionary<string, object>) new Dictionary<string, object>((IEqualityComparer<string>) StringComparer.Ordinal);
     38     }
     39 
     40     /// <summary>State values about the authentication session.</summary>
     41     public IDictionary<string, string> Items { get; }
     42 
     43     /// <summary>
     44     /// Collection of parameters that are passed to the authentication handler. These are not intended for
     45     /// serialization or persistence, only for flowing data between call sites.
     46     /// </summary>
     47     public IDictionary<string, object> Parameters { get; }
     48 
     49     /// <summary>
     50     /// Gets or sets whether the authentication session is persisted across multiple requests.
     51     /// </summary>
     52     public bool IsPersistent
     53     {
     54       get
     55       {
     56         return this.GetString(".persistent") != null;
     57       }
     58       set
     59       {
     60         this.SetString(".persistent", value ? string.Empty : (string) null);
     61       }
     62     }
     63 
     64     /// <summary>
     65     /// Gets or sets the full path or absolute URI to be used as an http redirect response value.
     66     /// </summary>
     67     public string RedirectUri
     68     {
     69       get
     70       {
     71         return this.GetString(".redirect");
     72       }
     73       set
     74       {
     75         this.SetString(".redirect", value);
     76       }
     77     }
     78 
     79     /// <summary>
     80     /// Gets or sets the time at which the authentication ticket was issued.
     81     /// </summary>
     82     public DateTimeOffset? IssuedUtc
     83     {
     84       get
     85       {
     86         return this.GetDateTimeOffset(".issued");
     87       }
     88       set
     89       {
     90         this.SetDateTimeOffset(".issued", value);
     91       }
     92     }
     93 
     94     /// <summary>
     95     /// Gets or sets the time at which the authentication ticket expires.
     96     /// </summary>
     97     public DateTimeOffset? ExpiresUtc
     98     {
     99       get
    100       {
    101         return this.GetDateTimeOffset(".expires");
    102       }
    103       set
    104       {
    105         this.SetDateTimeOffset(".expires", value);
    106       }
    107     }
    108 
    109     /// <summary>
    110     /// Gets or sets if refreshing the authentication session should be allowed.
    111     /// </summary>
    112     public bool? AllowRefresh
    113     {
    114       get
    115       {
    116         return this.GetBool(".refresh");
    117       }
    118       set
    119       {
    120         this.SetBool(".refresh", value);
    121       }
    122     }
    123 
    124     /// <summary>
    125     /// Get a string value from the <see cref="P:Microsoft.AspNetCore.Authentication.AuthenticationProperties.Items" /> collection.
    126     /// </summary>
    127     /// <param name="key">Property key.</param>
    128     /// <returns>Retrieved value or <c>null</c> if the property is not set.</returns>
    129     public string GetString(string key)
    130     {
    131       string str;
    132       return !this.Items.TryGetValue(key, out str) ? (string) null : str;
    133     }
    134 
    135     /// <summary>
    136     /// Set a string value in the <see cref="P:Microsoft.AspNetCore.Authentication.AuthenticationProperties.Items" /> collection.
    137     /// </summary>
    138     /// <param name="key">Property key.</param>
    139     /// <param name="value">Value to set or <c>null</c> to remove the property.</param>
    140     public void SetString(string key, string value)
    141     {
    142       if (value != null)
    143       {
    144         this.Items[key] = value;
    145       }
    146       else
    147       {
    148         if (!this.Items.ContainsKey(key))
    149           return;
    150         this.Items.Remove(key);
    151       }
    152     }
    153 
    154     /// <summary>
    155     /// Get a parameter from the <see cref="P:Microsoft.AspNetCore.Authentication.AuthenticationProperties.Parameters" /> collection.
    156     /// </summary>
    157     /// <typeparam name="T">Parameter type.</typeparam>
    158     /// <param name="key">Parameter key.</param>
    159     /// <returns>Retrieved value or the default value if the property is not set.</returns>
    160     public T GetParameter<T>(string key)
    161     {
    162       object obj1;
    163       return this.Parameters.TryGetValue(key, out obj1) && obj1 is T obj2 ? obj2 : default (T);
    164     }
    165 
    166     /// <summary>
    167     /// Set a parameter value in the <see cref="P:Microsoft.AspNetCore.Authentication.AuthenticationProperties.Parameters" /> collection.
    168     /// </summary>
    169     /// <typeparam name="T">Parameter type.</typeparam>
    170     /// <param name="key">Parameter key.</param>
    171     /// <param name="value">Value to set.</param>
    172     public void SetParameter<T>(string key, T value)
    173     {
    174       this.Parameters[key] = (object) value;
    175     }
    176 
    177     /// <summary>
    178     /// Get a bool value from the <see cref="P:Microsoft.AspNetCore.Authentication.AuthenticationProperties.Items" /> collection.
    179     /// </summary>
    180     /// <param name="key">Property key.</param>
    181     /// <returns>Retrieved value or <c>null</c> if the property is not set.</returns>
    182     protected bool? GetBool(string key)
    183     {
    184       string str;
    185       bool result;
    186       return this.Items.TryGetValue(key, out str) && bool.TryParse(str, out result) ? new bool?(result) : new bool?();
    187     }
    188 
    189     /// <summary>
    190     /// Set a bool value in the <see cref="P:Microsoft.AspNetCore.Authentication.AuthenticationProperties.Items" /> collection.
    191     /// </summary>
    192     /// <param name="key">Property key.</param>
    193     /// <param name="value">Value to set or <c>null</c> to remove the property.</param>
    194     protected void SetBool(string key, bool? value)
    195     {
    196       if (value.HasValue)
    197       {
    198         this.Items[key] = value.Value.ToString();
    199       }
    200       else
    201       {
    202         if (!this.Items.ContainsKey(key))
    203           return;
    204         this.Items.Remove(key);
    205       }
    206     }
    207 
    208     /// <summary>
    209     /// Get a DateTimeOffset value from the <see cref="P:Microsoft.AspNetCore.Authentication.AuthenticationProperties.Items" /> collection.
    210     /// </summary>
    211     /// <param name="key">Property key.</param>
    212     /// <returns>Retrieved value or <c>null</c> if the property is not set.</returns>
    213     protected DateTimeOffset? GetDateTimeOffset(string key)
    214     {
    215       string input;
    216       DateTimeOffset result;
    217       return this.Items.TryGetValue(key, out input) && DateTimeOffset.TryParseExact(input, "r", (IFormatProvider) CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out result) ? new DateTimeOffset?(result) : new DateTimeOffset?();
    218     }
    219 
    220     /// <summary>
    221     /// Set a DateTimeOffset value in the <see cref="P:Microsoft.AspNetCore.Authentication.AuthenticationProperties.Items" /> collection.
    222     /// </summary>
    223     /// <param name="key">Property key.</param>
    224     /// <param name="value">Value to set or <c>null</c> to remove the property.</param>
    225     protected void SetDateTimeOffset(string key, DateTimeOffset? value)
    226     {
    227       if (value.HasValue)
    228       {
    229         this.Items[key] = value.Value.ToString("r", (IFormatProvider) CultureInfo.InvariantCulture);
    230       }
    231       else
    232       {
    233         if (!this.Items.ContainsKey(key))
    234           return;
    235         this.Items.Remove(key);
    236       }
    237     }
    238   }
    View Code

    IClaimsTransformation

     1  public interface IClaimsTransformation
     2   {
     3     /// <summary>
     4     /// Provides a central transformation point to change the specified principal.
     5     /// Note: this will be run on each AuthenticateAsync call, so its safer to
     6     /// return a new ClaimsPrincipal if your transformation is not idempotent.
     7     /// </summary>
     8     /// <param name="principal">The <see cref="T:System.Security.Claims.ClaimsPrincipal" /> to transform.</param>
     9     /// <returns>The transformed principal.</returns>
    10     Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal);
    11   }
    View Code

    这个接口可以为传入的principal提供转换,适合全局为principal添加一些额外的claim。

  • 相关阅读:
    maven的tomcat插件如何进行debug调试
    jre,jdk,jvm的关系
    maven私服Nexus3.2的使用
    Markdown插入图表
    GAME-BASED LEARNING
    Game Based Learning: Why Does it Work?
    31 Game-Based Learning Resources for Educators
    Gamification and Game-Based Learning
    Gamification vs. Game-Based Learning
    WHAT IS GAME-BASED LEARNING?
  • 原文地址:https://www.cnblogs.com/pangjianxin/p/9388224.html
Copyright © 2020-2023  润新知