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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM