Article directory
- Aspnetcore3.1 source code resolution directory
- Aspnetcore3.1? Security source resolution? 2? Authentication? Core project
- Aspnetcore3.1 source code resolution authentication cookies
- Aspnetcore3.1 ﹣ security source resolution ﹣ 4 ﹣ authentication ﹣ jwtbear
- Aspnetcore3.1 ﹣ security source resolution ﹣ 5 ﹣ authentication ﹣ OAuth
- Aspnetcore3.1 source code resolution 6 authentication openidconnect
- Aspnetcore3.1? Security source resolution? 7? Authentication? Other
- Aspnetcore3.1 source code resolution authorization framework
Dependency injection
The framework provides three dependency injection overload methods.
//Injection certification service services.AddAuthentication(); //Inject authentication service and make default schema name services.AddAuthentication("Cookies"); //Inject authentication service and set configuration item services.AddAuthentication(config => { });
Look at the injection code
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 injects the core object of the authentication service. This method is in the Authentication.Core project, which defines the core object of the authentication service and the core interface in the Authentication.Abstractions project.
The AddAuthenticationCore method injects IAuthenticationService, iclaimstranformation, 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
Authentication service, which defines five methods
- AuthenticateAsync: authentication
- ChallengeAsync: challenge, verification and certification
- ForbidAsync: prohibit authentication
- SignInAsync: sign in
- SignOutAsync: sign out
<div class="mermaid"> classDiagram class IAuthenticationService{ +AuthenticateAsync(HttpContext context, string scheme) +ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties) +ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties) +SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) +SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties) } </div>
Through the source code of the AuthenticateAsync method, it can be seen that the AuthenticateService only acts as the controller, validates the schema, obtains the handler according to the schema, and the main authentication logic is handled by the handler. Other methods are basically the same logic.
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
<div class="mermaid"> classDiagram class IClaimsTransformation{ +TransformAsync(ClaimsPrincipal principal) } </div>
The interface has only one method for converting Claims. Nopclaimstransformation, which is injected by default, will not do anything. If you need to deal with Claims, you can implement iclaimstranformation and override injection.
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
<div class="mermaid"> classDiagram class IAuthenticationHandlerProvider{ +GetHandlerAsync(HttpContext context, string authenticationScheme) } </div>
As mentioned above, the handler handles the main authentication business logic. This interface can obtain the handler according to the schema.
<script src="https://unpkg.com/mermaid/dist/mermaid.min.js"></script>
IAuthenticationSchemeProvider
<div class="mermaid"> classDiagram class IAuthenticationSchemeProvider{ +GetAllSchemesAsync() +GetSchemeAsync(string name) +GetDefaultAuthenticateSchemeAsync() +GetDefaultChallengeSchemeAsync() +GetDefaultForbidSchemeAsync() +GetDefaultSignInSchemeAsync() +GetDefaultSignOutSchemeAsync() +AddScheme(AuthenticationScheme scheme) +RemoveScheme(string name) +GetRequestHandlerSchemesAsync() } </div>
This interface mainly defines some schema operation methods.
AuthenticationScheme has three main properties, which are associated with handler through HandlerType.
<div class="mermaid"> classDiagram class AuthenticationScheme{ Name DisplayName HandlerType } </div>
Authentication process
< div class = "mergeid" > graph TD a (authentication options defines the Schema of five authentication actions) a -- > B1 (authentication) a -- > B2 (challenge) a -- > B3 (Forbidden) a -- > B4 (signin) a -- > B5 (singout) C (iauthenticationschemeprovider gets Schema) B1 -- > C B2 -- > C B3 -- > C B4 -- > C B5 -- > C C -- > d (iauthenticationhandlerprovider gets the handler corresponding to the Schema) d -- > E (process request) < / div >
Other
In addition to the core objects, auxiliary objects for data protection and decoding are injected
services.AddDataProtection(); services.AddWebEncoders();
Authentication Middleware
The middleware will first find the implementation of IAuthenticationRequestHandler in the container. If the handler is not empty, the HandleRequestAsync method of the handler will be executed. IAuthenticationRequestHandler is usually used in remote authentication (such as OAuth, OIDC, etc.).
If there is no implementation of IAuthenticationRequestHandler, the default schema will be found, and the AuthenticationAsync method of the handler corresponding to the default schema will be executed. After the authentication is successful, the User object of HttpContext will be assigned a value.
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); }
Source: https://www.cnblogs.com/holdingong/p/12521089.html