今天咱們再來了解一個很重要的接口IAuthenticationService的實現類AuthenticationService:async
public class AuthenticationService : IAuthenticationService { public AuthenticationService(IAuthenticationSchemeProvider schemes, IAuthenticationHandlerProvider handlers, IClaimsTransformation transform) { Schemes = schemes; Handlers = handlers; Transform = transform; } 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 defaultScheme = await Schemes.GetDefaultAuthenticateSchemeAsync(); scheme = defaultScheme?.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 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; } /// <summary> /// Challenge the specified authentication scheme. /// </summary> /// <param name="context">The <see cref="HttpContext"/>.</param> /// <param name="scheme">The name of the authentication scheme.</param> /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param> /// <returns>A task.</returns> public virtual async Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties) { if (scheme == null) { var defaultChallengeScheme = await Schemes.GetDefaultChallengeSchemeAsync(); scheme = defaultChallengeScheme?.Name; if (scheme == null) { throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultChallengeScheme found."); } } var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { throw await CreateMissingHandlerException(scheme); } await handler.ChallengeAsync(properties); } /// <summary> /// Forbid the specified authentication scheme. /// </summary> public virtual async Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties) { if (scheme == null) { var defaultForbidScheme = await Schemes.GetDefaultForbidSchemeAsync(); scheme = defaultForbidScheme?.Name; ... } var handler = await Handlers.GetHandlerAsync(context, scheme);
...await handler.ForbidAsync(properties); } /// <summary> /// Sign a principal in for the specified authentication scheme. /// </summary> public virtual async Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) {
...
if (scheme == null) { var defaultScheme = await Schemes.GetDefaultSignInSchemeAsync(); scheme = defaultScheme?.Name; ... } var handler = await Handlers.GetHandlerAsync(context, scheme); ...
var signInHandler = handler as IAuthenticationSignInHandler; ...
await signInHandler.SignInAsync(principal, properties); } /// <summary> /// Sign out the specified authentication scheme. /// </summary> public virtual async Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties) { if (scheme == null) { var defaultScheme = await Schemes.GetDefaultSignOutSchemeAsync(); scheme = defaultScheme?.Name; if (scheme == null) { throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultSignOutScheme found."); } } var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { throw await CreateMissingSignOutHandlerException(scheme); } var signOutHandler = handler as IAuthenticationSignOutHandler; if (signOutHandler == null) { throw await CreateMismatchedSignOutHandlerException(scheme, handler); } await signOutHandler.SignOutAsync(properties); }
}
該類經過構造方法,將咱們前兩篇中講到了IAuthenticationSchemeProvider和IAuthenticationHandlerProvider注入了進來,第三個參數不是很重要就飄過了。接下來咱們看看它的這幾個方法AuthenticateAsync、ChallengeAsync、ForbidAsync、SignInAsync和SignOutAsync等方法,他們的套路幾乎都同樣的,經過注入進來的兩個接口的實例,最終得到到IAuthenticationHandler接口實例,並調用同名方法。ide
關於IAuthenticationService、IAuthenticationHandlerProvider和IAuthenticationSchemeProvider咱們又是何時注入到服務容器裏去的呢?它是在AuthenticationCoreServiceCollectionExtensions這個靜態類中的AddAuthenticationCore擴展方法注入到容器中的,還有AuthenticationOptions也是在這裏注入到依賴注入系統的容器中的:oop
public static class AuthenticationCoreServiceCollectionExtensions { public static IServiceCollection AddAuthenticationCore(this IServiceCollection services) {
... services.TryAddScoped<IAuthenticationService, AuthenticationService>(); services.TryAddSingleton<IClaimsTransformation, NoopClaimsTransformation>(); // Can be replaced with scoped ones that use DbContext services.TryAddScoped<IAuthenticationHandlerProvider, AuthenticationHandlerProvider>(); services.TryAddSingleton<IAuthenticationSchemeProvider, AuthenticationSchemeProvider>(); return services; } public static IServiceCollection AddAuthenticationCore(this IServiceCollection services, Action<AuthenticationOptions> configureOptions) { ... services.AddAuthenticationCore(); services.Configure(configureOptions); return services; } }
該擴展方法是在Startup的ConfigureServices方法調用的。這個就不貼代碼了。this
注入完之後呢?怎麼使用呢?爲了方便使用,aspnetcore爲咱們在外面又裹了一層,那就是AuthenticationHttpContextExtensions爲HttpContext添加的擴展方法。咱們能夠在Controller以下調用:spa
public class HomeController : Controller { public IActionResult Index() { var result = HttpContext.AuthenticateAsync(); return View(result.Result); } }
至此認證相關的核心元素介紹完成,本篇到此結束。code