7年測試《幻想地球》Steam版5月25日正式發售 太空殖民模擬
------------恢復內容開始------------
這篇文章主要介紹了ASP.NET Core Authentication認證實現方法,文中通過示例程式碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
追本溯源,從使用開始
首先看一下我們通常是如何使用微軟自帶的認證,一般在Startup裡面配置我們所需的依賴認證服務,這裡通過JWT的認證方式講解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public void ConfigureServices(IServiceCollection services) {
services.AddAuthentication(authOpt =>
{
authOpt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
authOpt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
//配置自己所要驗證的引數
};
});
}
|
我們來看一下原始碼AddAuthentication主要做了什麼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public static class AuthenticationServiceCollectionExtensions
{
public static AuthenticationBuilder AddAuthentication( this IServiceCollection services, Action<AuthenticationOptions> configureOptions)
{
if (services == null )
throw new ArgumentNullException(nameof (services));
if (configureOptions == null )
throw new ArgumentNullException(nameof (configureOptions));
AuthenticationBuilder authenticationBuilder = services.AddAuthentication();
services.Configure<AuthenticationOptions>(configureOptions);
return authenticationBuilder;
}
public static AuthenticationBuilder AddAuthentication( this IServiceCollection services)
{
if (services == null )
throw new ArgumentNullException(nameof (services));
services.AddAuthenticationCore();
services.AddDataProtection();
services.AddWebEncoders();
services.TryAddSingleton<ISystemClock, SystemClock>();
return new AuthenticationBuilder(services);
}
public static AuthenticationBuilder AddAuthentication(
this IServiceCollection services,
string defaultScheme)
{
return services.AddAuthentication((Action<AuthenticationOptions>) (o => o.DefaultScheme = defaultScheme));
}
.....
}
|
ConfigureServices方法基本都是服務的註冊,基於微軟的風格,這裡的AddAuthenticationCore肯定是我們的認證服務註冊方法,來看一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public static class AuthenticationCoreServiceCollectionExtensions
{
/// <summary>
/// Add core authentication services needed for <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationService" />.
/// </summary>
public static IServiceCollection AddAuthenticationCore(
this IServiceCollection services)
{
if (services == null )
throw new ArgumentNullException(nameof (services));
services.TryAddScoped<IAuthenticationService, AuthenticationService>();
services.TryAddSingleton<IClaimsTransformation, NoopClaimsTransformation>();
services.TryAddScoped<IAuthenticationHandlerProvider, AuthenticationHandlerProvider>();
services.TryAddSingleton<IAuthenticationSchemeProvider, AuthenticationSchemeProvider>();
return services;
}
/// <summary>
/// Add core authentication services needed for <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationService" />.
/// </summary>
public static IServiceCollection AddAuthenticationCore(
this IServiceCollection services,
Action<AuthenticationOptions> configureOptions)
{
if (services == null )
throw new ArgumentNullException(nameof (services));
if (configureOptions == null )
throw new ArgumentNullException(nameof (configureOptions));
services.AddAuthenticationCore();
services.Configure<AuthenticationOptions>(configureOptions);
return services;
}
}
|
我們看到這裡主要註冊了AuthenticationService, AuthenticationHandlerProvider, AuthenticationSchemeProvider這三個物件,如文章開頭所說,追本溯源,從使用開始,我們先看一下這三個物件是如何在認證體系中使用的,且是如何發揮作用的。
從使用開始
看一下我們的認證管道構建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseAuthentication();
...
}
public static class AuthAppBuilderExtensions
{
public static IApplicationBuilder UseAuthentication( this IApplicationBuilder app)
{
if (app == null )
throw new ArgumentNullException(nameof (app));
return app.UseMiddleware<AuthenticationMiddleware>();
}
}
|
這裡使用了約定的註冊方式UseMiddleware,並且指定使用中介軟體AuthenticationMiddleware
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
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())
{
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);
}
}
|
在繼續往下之前,我們先看一下這個認證中介軟體的作用結果,當認證通過時,在HttpContext的User屬性(ClaimPrincipal)賦予身份標識,所以在後續的請求管道中都是基於認證結果中的身份標識做鑑權,這個我們會在後面的實際操作中會提到。
言歸正傳,在這裡引出了我們的兩個物件AuthenticationHandlerProvider,AuthenticationSchemeProvider。
重要物件講解
IAuthenticationSchemeProvider
從名字來看,IAuthenticationSchemeProvider的作用應該是提供Scheme的,這也是Provider在微軟的風格里面起的作用(類似於工廠模式)。
這個Scheme是什麼呢?很明顯,在Framework時代,也是有基於不同Scheme驗證的,比如Bearer,Cookie,在Aspnet Core中定義不同的Scheme代表著不同的認證處理方式,具體體現是在每個Scheme中包含對應的IAuthenticationHandler型別的Handler,由它來完成跟自身Scheme相關的認證處理。如果沒有定義會怎麼樣?仔細看上面這塊原始碼,只有當AuthenticationScheme不為空時才會做認證,否則一旦在Controller打上鑑權標籤[Authorize],將會直接返回401,所以我們必須指定自己的Scheme。
那麼我們在哪裡指定我們的Scheme類似呢?我們先返回到ConfigureService的AddJwtBearer,使用過的朋友們肯定知道,這裡獲取的Scheme是我們在ConfigureService通過Addxxx scheme指定的Scheme型別。這裡我們是使用JWT的
在這裡指定了TOptions 為JwtBearerOptions,而THandler為JwtBearerHandler。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public virtual AuthenticationBuilder AddScheme<TOptions, THandler>(
string authenticationScheme,
string displayName,
Action<TOptions> configureOptions)
where TOptions : AuthenticationSchemeOptions, new ()
where THandler : AuthenticationHandler<TOptions>
{
return this .AddSchemeHelper<TOptions, THandler>(authenticationScheme, displayName, configureOptions);
}
private AuthenticationBuilder AddSchemeHelper<TOptions, THandler>(
string authenticationScheme,
string displayName,
Action<TOptions> configureOptions)
where TOptions : class , new ()
where THandler : class , IAuthenticationHandler
{
this .Services.Configure<AuthenticationOptions>((Action<AuthenticationOptions>) (o => o.AddScheme(authenticationScheme, (Action<AuthenticationSchemeBuilder>) (scheme =>
{
scheme.HandlerType = typeof (THandler);
scheme.DisplayName = displayName;
}))));
if (configureOptions != null )
this .Services.Configure<TOptions>(authenticationScheme, configureOptions);
this .Services.AddTransient<THandler>();
return this ;
}
|
注意這裡TOptions 是需要繼承AuthenticationSchemeOptions的,在這裡是JwtBearerOptions,而THandler是AuthenticationHandler<TOptions>型別的Handler,在這裡是JwtBearerHandler。
我們回到Scheme的分析繼續往下,首先看一下AuthenticationScheme的定義
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public class AuthenticationScheme
{
/// <summary>Constructor.</summary>
public AuthenticationScheme( string name, string displayName, Type handlerType)
{
if (name == null )
throw new ArgumentNullException(nameof (name));
if (handlerType == (Type) null )
throw new ArgumentNullException(nameof (handlerType));
if (! typeof (IAuthenticationHandler).IsAssignableFrom(handlerType))
throw new ArgumentException( "handlerType must implement IAuthenticationHandler." );
this .Name = name;
this .HandlerType = handlerType;
this .DisplayName = displayName;
}
/// <summary>The name of the authentication scheme.</summary>
public string Name { get ; }
/// <summary>
/// The display name for the scheme. Null is valid and used for non user facing schemes.
/// </summary>
public string DisplayName { get ; }
/// <summary>
/// The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationHandler" /> type that handles this scheme.
/// </summary>
public Type HandlerType { get ; }
}
|
在這裡可以看到,如果要使用Aspnet Core自身的認證體系,需先註冊Scheme,並且該Scheme必須指定一個型別為IAuthenticationHandler的Handler,否則會丟擲異常。(這個其實在AddxxxScheme的時候已經指定了AuthenticationHandler)
我們再看一下IAuthenticationSchemeProvider的GetRequestHandlerSchemesAsync方法做了什麼
1 2 3 4 |
public virtual Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync()
{
return Task.FromResult<IEnumerable<AuthenticationScheme>>((IEnumerable<AuthenticationScheme>) this ._requestHandlers);
}
|
這東西返回了_requestHandlers,這是什麼?看程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
public class AuthenticationSchemeProvider : IAuthenticationSchemeProvider
{
private readonly object _lock = new object ();
private readonly AuthenticationOptions _options;
private readonly IDictionary< string , AuthenticationScheme> _schemes;
private readonly List<AuthenticationScheme> _requestHandlers;
/// <summary>
/// Creates an instance of <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationSchemeProvider" />
/// using the specified <paramref name="options" />,
/// </summary>
public AuthenticationSchemeProvider(IOptions<AuthenticationOptions> options)
: this (options, (IDictionary< string , AuthenticationScheme>) new Dictionary< string , AuthenticationScheme>((IEqualityComparer< string >) StringComparer.Ordinal))
{
}
/// <summary>
/// Creates an instance of <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticationSchemeProvider" />
/// using the specified <paramref name="options" /> and <paramref name="schemes" />.
/// </summary>
protected AuthenticationSchemeProvider(
IOptions<AuthenticationOptions> options,
IDictionary< string , AuthenticationScheme> schemes)
{
this ._options = options.Value;
IDictionary< string , AuthenticationScheme> dictionary = schemes;
if (dictionary == null )
throw new ArgumentNullException(nameof (schemes));
this ._schemes = dictionary;
this ._requestHandlers = new List<AuthenticationScheme>();
foreach (AuthenticationSchemeBuilder scheme in this ._options.Schemes)
this .AddScheme(scheme.Build());
}
public virtual void AddScheme(AuthenticationScheme scheme)
{
if ( this ._schemes.ContainsKey(scheme.Name))
throw new InvalidOperationException( "Scheme already exists: " + scheme.Name);
lock ( this ._lock)
{
if ( this ._schemes.ContainsKey(scheme.Name))
throw new InvalidOperationException( "Scheme already exists: " + scheme.Name);
if ( typeof (IAuthenticationRequestHandler).IsAssignableFrom(scheme.HandlerType))
this ._requestHandlers.Add(scheme);
this ._schemes[scheme.Name] = scheme;
}
}
.....
}
|
這東西就是把我們在認證註冊服務中指定的scheme,通過解析出的AuthenticationSchemeProvider 的建構函式載入來的,進而返回一系列的List<AuthenticationScheme>,OK拿到這些scheme之後有什麼用呢?這裡引出了我們的第二個物件AuthenticationHandlerProvider,下面我們來了解一下。
IAuthenticationHandlerProvider
我們看到,AuthenticationMiddleware中用到了IAuthenticationHandlerProvider的GetHandlerAsync方法,那我們先看一下這個方法的作用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public class AuthenticationHandlerProvider : IAuthenticationHandlerProvider
{
private Dictionary< string , IAuthenticationHandler> _handlerMap = new Dictionary< string , IAuthenticationHandler>((IEqualityComparer< string >) StringComparer.Ordinal);
/// <summary>Constructor.</summary>
public AuthenticationHandlerProvider(IAuthenticationSchemeProvider schemes)
{
this .Schemes = schemes;
}
/// <summary>
/// The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationHandlerProvider" />.
/// </summary>
public IAuthenticationSchemeProvider Schemes { get ; }
/// <summary>Returns the handler instance that will be used.</summary>
public async Task<IAuthenticationHandler> GetHandlerAsync( HttpContext context, string authenticationScheme)
{
if ( this ._handlerMap.ContainsKey(authenticationScheme))
return this ._handlerMap[authenticationScheme];
AuthenticationScheme schemeAsync = await this .Schemes.GetSchemeAsync(authenticationScheme);
if (schemeAsync == null )
return (IAuthenticationHandler) null ;
IAuthenticationHandler handler = (context.RequestServices.GetService(schemeAsync.HandlerType) ?? ActivatorUtilities.CreateInstance(context.RequestServices, schemeAsync.HandlerType)) as IAuthenticationHandler;
if (handler != null )
{
await handler.InitializeAsync(schemeAsync, context);
this ._handlerMap[authenticationScheme] = handler;
}
return handler;
}
}
|
在建立Handler的時候,是先從AuthenticationScheme中獲取,如果不存在則通過ActivatorUtilities建立。 獲取到Handle後,將會放在_handlerMap字典裡面,當下次獲取Handler的時候,將直接從快取中獲取。
IAuthenticationService
這個物件是在AuthenticationMiddleware中最後才用到的,而且是基於HttpContext的擴充套件被呼叫
1 2 3 4 5 6 7 |
public static class AuthenticationHttpContextExtensions
{
public static Task<AuthenticateResult> AuthenticateAsync( this HttpContext context, string scheme) =>
context.RequestServices.GetRequiredService<IAuthenticationService>().AuthenticateAsync(context, scheme);
....
}
|
這裡主要呼叫了IAuthenticationService的AuthenticateAsync方法,看一下這個方法做了什麼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public class AuthenticationService : IAuthenticationService
{
public IAuthenticationSchemeProvider Schemes { get ; }
public IAuthenticationHandlerProvider Handlers { get ; }
public IClaimsTransformation Transform { get ; }
public virtual async Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme)
{
if (scheme == null )
{
var scheme = (await this .Schemes.GetDefaultAuthenticateSchemeAsync())?.Name;
if (scheme == null )
throw new InvalidOperationException($ "No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found." );
}
var handler = await Handlers.GetHandlerAsync(context, scheme);
if (handler == null )
throw await this .CreateMissingHandlerException(scheme);
AuthenticateResult result = await handler.AuthenticateAsync();
if (result != null && result.Succeeded)
return AuthenticateResult.Success( new AuthenticationTicket(await Transform.TransformAsync(result.Principal), result.Properties, result.Ticket.AuthenticationScheme));
return result;
}
}
|
這裡其實就是我們在前面講的根據Scheme獲取對應的AuthenticationHandler,然後呼叫AuthenticateAsync()方法,這個方法呼叫了核心方法HandleAuthenticateOnceAsync,然後再呼叫HandleAuthenticateAsync()這個核心的認證方法。
從上圖看到這個HandleAuthenticateAsync是個抽象方法,我們的子類都需要實現這個方法的動作,基於本文的例子,我們看一下JwtBearerHandler的一個實際認證。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
public class JwtBearerHandler : AuthenticationHandler<JwtBearerOptions>
{
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
JwtBearerHandler jwtBearerHandler = this ;
string token = ( string ) null ;
object obj;
AuthenticationFailedContext authenticationFailedContext;
int num;
try
{
MessageReceivedContext messageReceivedContext = new MessageReceivedContext(jwtBearerHandler.Context, jwtBearerHandler.Scheme, jwtBearerHandler.Options);
await jwtBearerHandler.Events.MessageReceived(messageReceivedContext);
if (messageReceivedContext.Result != null )
return messageReceivedContext.Result;
token = messageReceivedContext.Token;
if ( string .IsNullOrEmpty(token))
{
string header = ( string ) jwtBearerHandler.Request.Headers[ "Authorization" ];
if ( string .IsNullOrEmpty(header))
return AuthenticateResult.NoResult();
if (header.StartsWith( "Bearer " , StringComparison.OrdinalIgnoreCase))
token = header.Substring( "Bearer " .Length).Trim();
if ( string .IsNullOrEmpty(token))
return AuthenticateResult.NoResult();
}
if (jwtBearerHandler._configuration == null && jwtBearerHandler.Options.ConfigurationManager != null )
{
OpenIdConnectConfiguration configurationAsync = await jwtBearerHandler.Options.ConfigurationManager.GetConfigurationAsync(jwtBearerHandler.Context.RequestAborted);
jwtBearerHandler._configuration = configurationAsync;
}
TokenValidationParameters validationParameters1 = jwtBearerHandler.Options.TokenValidationParameters.Clone();
if (jwtBearerHandler._configuration != null )
{
string [] strArray = new string [1]
{
jwtBearerHandler._configuration.Issuer
};
TokenValidationParameters validationParameters2 = validationParameters1;
IEnumerable< string > validIssuers = validationParameters1.get_ValidIssuers();
object obj1 = (validIssuers != null ? ( object ) validIssuers.Concat< string >((IEnumerable< string >) strArray) : ( object ) null ) ?? ( object ) strArray;
validationParameters2.set_ValidIssuers((IEnumerable< string >) obj1);
TokenValidationParameters validationParameters3 = validationParameters1;
IEnumerable<SecurityKey> issuerSigningKeys = validationParameters1.get_IssuerSigningKeys();
IEnumerable<SecurityKey> securityKeys = (issuerSigningKeys != null ? issuerSigningKeys.Concat<SecurityKey>((IEnumerable<SecurityKey>) jwtBearerHandler._configuration.get_SigningKeys()) : (IEnumerable<SecurityKey>) null ) ?? (IEnumerable<SecurityKey>) jwtBearerHandler._configuration.get_SigningKeys();
validationParameters3.set_IssuerSigningKeys(securityKeys);
}
List<Exception> exceptionList = (List<Exception>) null ;
foreach (ISecurityTokenValidator securityTokenValidator in (IEnumerable<ISecurityTokenValidator>) jwtBearerHandler.Options.SecurityTokenValidators)
{
if (securityTokenValidator.CanReadToken(token))
{
SecurityToken securityToken;
ClaimsPrincipal claimsPrincipal;
try
{
claimsPrincipal = securityTokenValidator.ValidateToken(token, validationParameters1, ref securityToken);
}
catch (Exception ex)
{
jwtBearerHandler.Logger.TokenValidationFailed(ex);
if (jwtBearerHandler.Options.RefreshOnIssuerKeyNotFound && jwtBearerHandler.Options.ConfigurationManager != null && ex is SecurityTokenSignatureKeyNotFoundException)
jwtBearerHandler.Options.ConfigurationManager.RequestRefresh();
if (exceptionList == null )
exceptionList = new List<Exception>(1);
exceptionList.Add(ex);
continue ;
}
jwtBearerHandler.Logger.TokenValidationSucceeded();
TokenValidatedContext validatedContext = new TokenValidatedContext(jwtBearerHandler.Context, jwtBearerHandler.Scheme, jwtBearerHandler.Options);
validatedContext.Principal = claimsPrincipal;
validatedContext.SecurityToken = securityToken;
TokenValidatedContext tokenValidatedContext = validatedContext;
await jwtBearerHandler.Events.TokenValidated(tokenValidatedContext);
if (tokenValidatedContext.Result != null )
return tokenValidatedContext.Result;
if (jwtBearerHandler.Options.SaveToken)
tokenValidatedContext.Properties.StoreTokens((IEnumerable<AuthenticationToken>) new AuthenticationToken[1]
{
new AuthenticationToken()
{
Name = "access_token" ,
Value = token
}
});
tokenValidatedContext.Success();
return tokenValidatedContext.Result;
}
}
if (exceptionList == null )
return AuthenticateResult.Fail( "No SecurityTokenValidator available for token: " + token ?? "[null]" );
authenticationFailedContext = new AuthenticationFailedContext(jwtBearerHandler.Context, jwtBearerHandler.Scheme, jwtBearerHandler.Options)
{
Exception = exceptionList.Count == 1 ? exceptionList[0] : (Exception) new AggregateException((IEnumerable<Exception>) exceptionList)
};
await jwtBearerHandler.Events.AuthenticationFailed(authenticationFailedContext);
return authenticationFailedContext.Result == null ? AuthenticateResult.Fail(authenticationFailedContext.Exception) : authenticationFailedContext.Result;
}
catch (Exception ex)
{
obj = ( object ) ex;
num = 1;
}
if (num == 1)
{
Exception ex = (Exception) obj;
jwtBearerHandler.Logger.ErrorProcessingMessage(ex);
authenticationFailedContext = new AuthenticationFailedContext(jwtBearerHandler.Context, jwtBearerHandler.Scheme, jwtBearerHandler.Options)
{
Exception = ex
};
await jwtBearerHandler.Events.AuthenticationFailed(authenticationFailedContext);
if (authenticationFailedContext.Result != null )
return authenticationFailedContext.Result;
Exception source = obj as Exception;
if (source == null )
throw obj;
ExceptionDispatchInfo.Capture(source).Throw();
authenticationFailedContext = (AuthenticationFailedContext) null ;
}
obj = ( object ) null ;
token = ( string ) null ;
AuthenticateResult authenticateResult;
return authenticateResult;
}
}
|
這個方法有點長,主要是從Request.Headers裡面獲取Authorization的Bearer出來解析,再在AddJwtBearer中傳入的委託引數JwtBearerOptions的TokenValidationParameters屬性作為依據進行對比來進行認證是否通過與否。
總結
本文對 ASP.NET Core 的認證流程做了一個原始碼分析流程介紹,由於是原始碼分析篇,所以可能會比較枯燥和苦澀難懂。在後面的真正使用過程中,然後再結合本篇的一個總結流程,相信大家會逐漸開朗。
- 在Startup類中的ConfigureServices方法通過新增AddAuthentication註冊我們最主要的三個物件AuthenticationService, AuthenticationHandlerProvider, AuthenticationSchemeProvider
- 通過AddAuthentication返回的AuthenticationBuilder 通過AddJwtBearer(或者AddCookie)來指定Scheme型別和需要驗證的引數
- 在Startup類中的Configure方法通過新增UseAuthentication註冊認證中介軟體
- 在認證過程中,通過AuthenticationSchemeProvider獲取正確的Scheme,在AuthenticationService中通過Scheme和AuthenticationHandlerProvider獲取正確的AuthenticationHandler,最後通過對應的AuthenticationHandler的AuthenticateAsync方法進行認證流程
------------恢復內容結束------------