系列文章目录

  • 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_核心项目
  • AspNetCore3.1_Secutiry源码解析_9_Authorization_Policy

依赖注入

框架提供了三个依赖注入重载方法。

//注入认证服务
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项目中定义了核心接口。

image

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:登出
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)
}

通过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();

版权声明:本文为holdengong原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/holdengong/p/12521089.html