Fork me on GitHub

.NetCore源码阅读笔记系列之HttpAbstractions(五) Authentication

说道认证&授权其实这块才是核心,这款跟前面Security这块有者紧密的联系,当然 HttpAbstractions 不光是认证、授权、还包含其他Http服务和中间价

接下来先就认证这块结合前面的Security作一个补充说明

前面 AddCookie 、OpenIdConnect、Google、QQ 等等不过是添加的认证策略方式,他们实现的授权接口都来至于我们的HttpAbstractions模块中的Authentication

只不过前面封装了扩展,看上起好像有点绕,比如OpenIdConnect我们来看下

builder.AddRemoteScheme<OpenIdConnectOptions, OpenIdConnectHandler>(authenticationScheme, displayName, configureOptions);

我之前说了的OpenIdConnectHandler的重要性,这个其实只不过实现了HttpAbstractions 模块下 Authentication中的抽象模块中的类及认证接口服务提供实现,可以看到OpenIdConnet 添加的远程认证策略AddRemoteScheme,实际就是 HttpAbstractions 中Authentication中的IAuthenticationHandler接口处理以及先关IAuthenticationSignInHandler、IAuthenticationSignOutHandler的实现,包括在OpenIdConnect 或者 Cookies等里面调用的SignIn SginOut 等操作,而通过下面的代码来实现

await handler.SignInAsync(principal, properties);

这里有一些疑问就是hanlder 是什么呢?这里就是提到前面的 AddScheme中策略问题了,其实就是提供认证处理接口

public IAuthenticationHandlerProvider Handlers { get; }

说道这里,就需要提到软件设计中经常会用到的一个步骤,那就是 Build 、Provider 、Handler  看到这三个东西是不是很熟悉

接下来我们来看下 AuthenticationSchemeBuilder 中的 Build构建,构建的时候指定了HandlerType ,其实这里的 HandlerType就是在AddScheme中指定了具体处理方式,注意这里的指定方式需要继承IAuthenticationHandler,当然也是在这里去构建

public void AddScheme<THandler>(string name, string displayName) where THandler : IAuthenticationHandler
            => AddScheme(name, b =>
            {
                b.DisplayName = displayName;
                b.HandlerType = typeof(THandler);
            });

其实我们可以这样来描述,我们现在在ConfigureServices添加好自己授权服务,假定我们没有参数,结合之前的OpenIdConnect例子,AddAuthenticationCore 、AddAuthentication其实都是扩展方法而已,里面其实实现了

IAuthenticationService 、IAuthenticationHandlerProvider、IAuthenticationSchemeProvider等服务的注册,下面我们这样来写,这里的CustomHandler是我自定义的处理策略handlertype,当然这里需要实现接口IAuthenticationHandler,当然还可以实现签入、签出相关接口

services.AddAuthenticationCore(options =>
            {
                options.AddScheme<CustomHandler>("name", "displayname");

            });
public class CustomHandler : IAuthenticationHandler
        {
            public Task<AuthenticateResult> AuthenticateAsync()
            {
                throw new NotImplementedException();
            }

            public Task ChallengeAsync(AuthenticationProperties properties)
            {
                throw new NotImplementedException();
            }

            public Task ForbidAsync(AuthenticationProperties properties)
            {
                throw new NotImplementedException();
            }

            public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
            {
                throw new NotImplementedException();
            }
        }

其实这里自己封装成一个类库其实就是类是AddOpenIdConnect这样的认证服务中间件了,比如我前面写的 AddCustom,然而你写了这些之后怎么来实现认证的呢?

这里就需要说到 UserAuthentication这个中间件了,下面我们来看下这个中间件处理什么? 其实说到这里就已经很清楚了,就是拿到认证服务提供,调用Handler处理认证,然后将认证信息写入到User中,下面就是AuthenticationMiddleware中间件要做的事情

 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);

通过这些文字,相信基本多这块有大志的了解了,希望能够帮助到大家

 

posted @ 2018-11-23 15:01  龙码精神  阅读(619)  评论(1编辑  收藏  举报