说道认证&授权其实这块才是核心,这款跟前面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);
通过这些文字,相信基本多这块有大志的了解了,希望能够帮助到大家