文章目錄
- AspNetCore3.1_Secutiry原始碼決議_1_目錄
- AspNetCore3.1_Secutiry原始碼決議_2_Authentication_核心專案
- AspNetCore3.1_Secutiry原始碼決議_3_Authentication_Cookies
- AspNetCore3.1_Secutiry原始碼決議_4_Authentication_JwtBear
- AspNetCore3.1_Secutiry原始碼決議_5_Authentication_OAuth
- AspNetCore3.1_Secutiry原始碼決議_6_Authentication_OpenIdConnect
- AspNetCore3.1_Secutiry原始碼決議_7_Authentication_其他
- AspNetCore3.1_Secutiry原始碼決議_8_Authorization_授權框架
依賴注入
框架提供了三個依賴注入多載方法,
//注入認證服務
services.AddAuthentication();
//注入認證服務并制定默認架構名
services.AddAuthentication("Cookies");
//注入認證服務并設定配置項
services.AddAuthentication(config =>
{
});
看看注入代碼
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);
}
AddAuthenticationCore注入了認證服務的核心物件,這個方法在Authentication.Core專案,這個專案定義了認證服務的核心物件,在Authentication.Abstractions專案中定義了核心介面,

AddAuthenticationCore方法注入了IAuthenticationService,IClaimsTransformation,IAuthenticationHandlerProvider,IAuthenticationSchemeProvider
public static IServiceCollection AddAuthenticationCore(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.TryAddScoped<IAuthenticationService, AuthenticationService>();
services.TryAddSingleton<IClaimsTransformation, NoopClaimsTransformation>(); // Can be replaced with scoped ones that use DbContext
services.TryAddScoped<IAuthenticationHandlerProvider, AuthenticationHandlerProvider>();
services.TryAddSingleton<IAuthenticationSchemeProvider, AuthenticationSchemeProvider>();
return services;
}
IAuthenticationService
認證服務,定義了五個方法
- AuthenticateAsync: 認證
- ChallengeAsync:挑戰,校驗認證
- ForbidAsync:禁止認證
- SignInAsync:登入
- SignOutAsync:登出
通過AuthenticateAsync方法源代碼可以看到,AuthenticateService只是做了控制器的角色,校驗schema,根據schema獲取handler,主要的認證邏輯是由handler處理,其他的方法基本也是這樣的邏輯,
public virtual async Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme)
{
if (scheme == null)
{
var defaultScheme = await Schemes.GetDefaultAuthenticateSchemeAsync();
scheme = defaultScheme?.Name;
if (scheme == null)
{
throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).");
}
}
var handler = await Handlers.GetHandlerAsync(context, scheme);
if (handler == null)
{
throw await CreateMissingHandlerException(scheme);
}
var result = await handler.AuthenticateAsync();
if (result != null && result.Succeeded)
{
var transformed = await Transform.TransformAsync(result.Principal);
return AuthenticateResult.Success(new AuthenticationTicket(transformed, result.Properties, result.Ticket.AuthenticationScheme));
}
return result;
}
IClaimsTransformation
classDiagram class IClaimsTransformation{ +TransformAsync(ClaimsPrincipal principal) }該介面只有一個方法,用于轉換Claims,默認注入的NoopClaimsTransformation,不會做任何操作,如果需要對Claims做一些處理,實作IClaimsTransformation并覆寫注入就可以了,
public class NoopClaimsTransformation : IClaimsTransformation
{
/// <summary>
/// Returns the principal unchanged.
/// </summary>
/// <param name="principal">The user.</param>
/// <returns>The principal unchanged.</returns>
public virtual Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
return Task.FromResult(principal);
}
}
IAuthenticationHandlerProvider
classDiagram class IAuthenticationHandlerProvider{ +GetHandlerAsync(HttpContext context, string authenticationScheme) }上面提到過handler處理了主要的認證業務邏輯,這個介面可以根據schema獲取handler,
IAuthenticationSchemeProvider
classDiagram class IAuthenticationSchemeProvider{ +GetAllSchemesAsync() +GetSchemeAsync(string name) +GetDefaultAuthenticateSchemeAsync() +GetDefaultChallengeSchemeAsync() +GetDefaultForbidSchemeAsync() +GetDefaultSignInSchemeAsync() +GetDefaultSignOutSchemeAsync() +AddScheme(AuthenticationScheme scheme) +RemoveScheme(string name) +GetRequestHandlerSchemesAsync() }該介面主要定義了一些schema的操作方法,
AuthenticationScheme主要有三個屬性,通過HandlerType與handler建立了關聯,
classDiagram class AuthenticationScheme{ Name DisplayName HandlerType }認證流程
graph TD A(AuthenticationOptions定義五個認證動作的Schema) A --> B1(Authenticate) A --> B2(Challenge) A --> B3(Forbid) A --> B4(SignIn) A --> B5(SingOut) C(IAuthenticationSchemeProvider獲取Schema) B1 --> C B2 --> C B3 --> C B4 --> C B5 --> C C --> D(IAuthenticationHandlerProvider獲取Schema對應的Handler) D --> E(處理請求)其他
除了核心物件,還注入了用于資料保護和解碼的輔助物件
services.AddDataProtection();
services.AddWebEncoders();
Authentication中間件
中間件會優先在容器中找IAuthenticationRequestHandler的實作,如果handler不為空的話,則執行handler的HandleRequestAsync方法,IAuthenticationRequestHandler通常在遠程認證(如:OAuth, OIDC等)中使用,
如果沒有IAuthenticationRequestHandler的實作,則會找默認schema,執行默認schema對應handler的AuthenticationAsync方法,認證成功后,給HttpContext的User物件賦值,
public async Task Invoke(HttpContext context)
{
context.Features.Set<IAuthenticationFeature>(new AuthenticationFeature
{
OriginalPath = context.Request.Path,
OriginalPathBase = context.Request.PathBase
});
// Give any IAuthenticationRequestHandler schemes a chance to handle the request
var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
{
var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler;
if (handler != null && await handler.HandleRequestAsync())
{
return;
}
}
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
if (result?.Principal != null)
{
context.User = result.Principal;
}
}
await _next(context);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/54783.html
標籤:.NET Core
