• 认证Authentication


    认证authentication,基于声明式认证

    基于HttpContext的认证的扩展,SignIn(成功会颁发一个加密的凭证)、SignOut、Authenticate (验证signin颁发证书,返回authenticationResult,表明用户身份)、Challenge(返回一个需要标识身份提示用户登录,通常返回401)、  Forbid (通用返回403)、 GetTocken,调用AuthenticationService同名方法执行

    在aspnetcore的http下authentication.abstrations与authentication.core对关键抽象进行描述,Security下则是Authentication则是具体的实现

    服务注入 AddAuthentication(),可以直接指定defaultscheme,可以使用委托方法指定AuthenticationOption下面的defaultscheme,authenticatescheme,signscheme,signoutscheme,defaultchallenge

    指定相应的hander。注入最重要AuthenticationService、 AuthenticationHandlerProvider、AuthenticationSchemeProvider三个重要对象

    services.AddAuthenticationCore();
    services.AddDataProtection();
    services.AddWebEncoders();
    services.TryAddSingleton<ISystemClock, SystemClock>();
    return new AuthenticationBuilder(services);
    
    public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, string defaultScheme)
                => services.AddAuthentication(o => o.DefaultScheme = defaultScheme);
    
    public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, Action<AuthenticationOptions> configureOptions) 
    
     services.Configure(configureOptions);

    通过AddAuthentication返回的AuthenticationBuilder,通过AddJwtBearer(或者AddCookie)来指定Scheme类型和需要验证的参数

       context.Services.AddAuthentication("Bearer")
                    .AddIdentityServerAuthentication(options =>
                    {
                        options.Authority = configuration["AuthServer:Authority"];
                        options.ApiName = configuration["AuthServer:ApiName"];
                        options.RequireHttpsMetadata = false;
                    });
    AddJwtBearer("Bearer+IdentityServerAuthenticationJwt") 
    增加 builder.AddScheme<JwtBearerOptions, JwtBearerHandler>("BearerIdentityServerAuthenticationJwt")
    首先在AuthenticationOptions增加BearerIdentityServerAuthenticationJwt,类型是JwtBearerHandler)注入JwtBearerOptions、JwtBearerHandler单例
    增加Bearer,类型是IdentityServerAuthenticationHandler,Authentication handler for validating both JWT and reference tokens
     public static AuthenticationBuilder AddIdentityServerAuthentication(this AuthenticationBuilder builder, string authenticationScheme, Action<IdentityServerAuthenticationOptions> configureOptions)
            {
                builder.AddJwtBearer(authenticationScheme + IdentityServerAuthenticationDefaults.JwtAuthenticationScheme, configureOptions: null);
                builder.AddOAuth2Introspection(authenticationScheme + IdentityServerAuthenticationDefaults.IntrospectionAuthenticationScheme, configureOptions: null);
    
                builder.Services.AddSingleton<IConfigureOptions<JwtBearerOptions>>(services =>
                {
                    var monitor = services.GetRequiredService<IOptionsMonitor<IdentityServerAuthenticationOptions>>();
                    return new ConfigureInternalOptions(monitor.Get(authenticationScheme), authenticationScheme);
                });
                
                builder.Services.AddSingleton<IConfigureOptions<OAuth2IntrospectionOptions>>(services =>
                {
                    var monitor = services.GetRequiredService<IOptionsMonitor<IdentityServerAuthenticationOptions>>();
                    return new ConfigureInternalOptions(monitor.Get(authenticationScheme), authenticationScheme);
                });
                
                return builder.AddScheme<IdentityServerAuthenticationOptions, IdentityServerAuthenticationHandler>(authenticationScheme, configureOptions);
            }

    在Startup类中的Configure方法通过添加UseAuthentication注册认证中间件(AuthenticationMiddleware),在认证过程中,通过AuthenticationSchemeProvider获取正确的Scheme,在AuthenticationService中通过Scheme和AuthenticationHandlerProvider获取正确的AuthenticationHandler,最后通过对应的AuthenticationHandler的AuthenticateAsync方法进行认证流程。

    GetRequestHandlerSchemesAsync(多个AuthenticationScheme)=》GetDefaultAuthenticateSchemeAsync(一个AuthenticationScheme、执行handle下的AuthenticateAsync方法,返回AuthenticateResult给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);
            }

    1、AuthenticationOption

    scheme:有cookie, bearer, oauth, openid等等,保存着IList<AuthenticationSchemeBuilder> schemes,SchemeMap

     DefaultScheme、DefaultAuthenticateScheme、DefaultSignInScheme、DefaultSignOutScheme、DefaultChallengeScheme、DefaultForbidScheme??

    什么时候赋值??schememap对应是哪个AuthenticationSchemeBuilder,即使用哪个IAuthenticationHandle(方法有InitializeAsync、AuthenticateAsync、ChallengeAsync、ForbidAsync,Signin SignOut方法单独出来)处理它的通用方法是AddScheme(),即增加到IList<AuthenticationSchemeBuilder>,每一个schemeName映射 Dictionary< schemeName  , AuthenticationSchemeBuilder> schememap

    AuthenticationSchemeBuilder:名字(scheme name)、展示名字、Type(IAuthenticationHandler)、用来build方法创建AuthenticationScheme (两者之前的差别)
     
    2、AuthenticationSchemeProvider,创建的时候,就从上面Option里面取出schemes,创建保存是IDictionary<string, AuthenticationScheme> _schemes;
    _requestHandlers:typeof(IAuthenticationRequestHandler).IsAssignableFrom(scheme.HandlerType) 的集合。
     
     3、authenticationHandlerProvider:是需要根据提供Scheme名字得到IAuthenticationHandler,它要使用IAuthenticationSchemeProvider,取出对应的AuthenticationScheme,再根据创建对应IAuthenticationHandle的实例。再进行初始化(赋值Scheme和HttpContext)。 
    IAuthenticationRequestHandler:是用于确定处理程序是否要参与请求处理。如果返回true,说明认证停止。通常有远程认证中使用
       
    4、AuthenticationService:使用哪个scheme,没有指定则使用default,使用这个scheme下定义的IAuthenticationHandler,创建IAuthenticationHandler  
    AuthenticateResult:它是AuthenticationHandler对象执行Authenticate方法的认证结果
    它有AuthenticationTick(核心对象、ClaimsPrincipal,AuthenticationScheme,在授权中验证scheme、AuthenticationProperties)、ClaimsPrincipal(用来给HttpContext.User)、AuthenticationProperties(et(表示证书颁发的相关信息,如颁发时间,过期时间,重定向地址等)),有success 、fail静态方法
     
    二、AuthenticationHandler

    它定义一个抽象方法HandleAuthenticateAsync,并使用HandleAuthenticateOnceAsync方法来保证其在每次认证只执行一次。而HandleAuthenticateAsync是认证的核心,交给具体的认证Handler负责实现。而对于 ChallengeAsync, ForbidAsync 等方法也提供了默认的实现。

    而对于HandleAuthenticateAsync的实现,大致的逻辑就是从请求中获取上面发放的身份令牌,然后解析成AuthenticationTicket,并经过一系列的验证,最终返回ClaimsPrincipal对象。

    jwtScheme=Bearer+IdentityServerAuthenticationJwt    =》使用是JwtBearerHandler

    introspectionScheme=Bearer+IdentityServerAuthenticationIntrospection 》对reference token处理

    在HttpContext.Item存储idsrv4:tokenvalidation:token

    RemoteAuthenticationHandler 便是所有远程认证的抽象基类了,它继承自AuthenticationHandler,并实现了IAuthenticationRequestHandler接口:

    RemoteAuthenticationHandler中核心的认证逻辑便是 HandleRequestAsync 方法,它主要包含2个步骤:

    首先执行一个抽象方法HandleRemoteAuthenticateAsync,由具体的Handler来实现,该方法返回的HandleRequestResult对象包含验证的结果(跳过,失败,成功等),在成功时会包含一个ticket对象若上一步验证成功,则根据返回的ticket,获取到ClaimsPrincipal对象,并调用其它认证Handler的Context.SignInAsync方法。

    远程Hander会在用户未登录时,指引用户跳转到认证服务器,登录成功后,解析认证服务器传回的凭证,最终依赖于本地Handler来保存身份令牌。当用户再次访问则无需经过远程Handler,直接交给本地Handler来处理。

     
     

    public interface IAuthenticationHandler
    {
    Task InitializeAsync(AuthenticationScheme scheme, HttpContext context);
    Task<AuthenticateResult> AuthenticateAsync();
    Task ChallengeAsync(AuthenticationProperties properties);
    Task ForbidAsync(AuthenticationProperties properties);
    }
     public interface IAuthenticationRequestHandler : IAuthenticationHandler
        {
            /// <summary>
            /// Returns true if request processing should stop.
            /// </summary>
            /// <returns><see langword="true" /> if request processing should stop.</returns>
            Task<bool> HandleRequestAsync();
        }
        public interface IAuthenticationSignInHandler : IAuthenticationSignOutHandler
        {
    
            Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties);
        }
        public interface IAuthenticationSignOutHandler : IAuthenticationHandler
        {
            Task SignOutAsync(AuthenticationProperties properties);
        }

     

  • 相关阅读:
    了解及使用IPV6
    天气预报API(六):中国气象频道、腾讯天气--“新编码”接口的测试
    天气预报API(五):城市代码--“新编码”和“旧编码” 对比
    天气预报API(三):免费接口测试(“旧编码”)
    nginx 配置反向代理和静态资源
    centos 7 安装mysql5.7
    java 重新学习 (四)
    java 重新学习 (三)
    java 重新学习 (二)
    h5唤醒手机拨打电话
  • 原文地址:https://www.cnblogs.com/cloudsu/p/12050483.html
Copyright © 2020-2023  润新知