SignInAsync,SignOutAsync:个人觉得这两个不应该放在这里,因为并不属于认证的职责,也不属于协议规定的内容。但是这两个方法确实需要抽象,应该单独抽取一个接口存放,至于为什么这样做,或许是因为以下原因:
1、对登入登出的抽象是和认证紧密结合的,大多数情况下认证资料的保存是需要在SignIn进行的,比如 Cookies Authentication 中间件就在SignIn方法里面做了Cookie的保存。
2、 AuthenticationManager 这个对象是处在 HttpContext
上下文里面的,本着面向抽象和封装的原则,放到其里面是合适的,这样能够很方便的用户对其调用。
关于 AuthenticationManager 已经介绍完了,是不是很简单呢?
IAuthenticationHandler
有些同学可能会问了,如果 AuthenticationManager 不提供接口的话,只是一个抽象类的话,那如果自定义认证方法就必须继承它,这对于开发者来说是不友好的,也违背了面向接口编程的理念。嗯,确实是这样,那么接口来了:
public interface IAuthenticationHandler { void GetDescriptions(DescribeSchemesContext context); Task AuthenticateAsync(AuthenticateContext context); Task ChallengeAsync(ChallengeContext context); Task SignInAsync(SignInContext context); Task SignOutAsync(SignOutContext context); }
这个接口是在 AuthenticationManager 实现类 DefaultAuthenticationManager 中延伸出来的,所以大家不用再去看里面的源码了,记住以后如果需要重写认证相关的东西,实现IAuthenticationHandler就可以了。
Authentication 中间件
对 IAuthenticationHandler 的初步实现,封装了 AuthenticationHandler 这个抽象类,把具体的核心功能都交给下游去实现了,下面的CookieAuthentication 中间件核心类 CookieAuthenticationHandler 就是继承自AuthenticationHandler, 知道这么多就够了。
CookieAuthentication 中间件
故事还要继续,奥巴马在接到小李递来的身份证和火车票之后,首先拿着火车票在一个二维码机器上扫描了一下,然后又拿着身份证在一个机器上刷了一下,经过核查,发现都没有问题。于是拿起印章在上面盖了一个 “ 验讫 ”。
这中间都发生了什么呢?
首先,在二维码扫描的过程,这个过程二维码机器会解析你火车票上的二维码,如果发现解析失败,会直接响应认证失败。也就是你别想进站了。
如果解析成功,就会得到你这个票据中的信息了,然后拿到你票据里面的的当事人信息进行验证是否被列为了铁路局黑名单中。
如果验证通过,则会给你颁发一个识别码,把符合你身份的一个识别码写入到你的火车票中和检票员旁边的电脑系统中,即 “ 验讫 ”。
话说这个验讫有点高级,它会向你的火车票芯片中写入一些信息,那么都写入些什么信息呢? 1、奥巴马个人的信息。2、验证途中的一些上下信息。3、使用的验证方案。
知道了,这些之后,那么就很容易实现这个验证方法了,对吧? 以下是 CookieAuthentication 中间件中的核心类 CookieAuthenticationHandler 的里面的核心方法HandleAuthenticateAsync(),同样你可以理解为实现的 IAuthenticationHandler 接口的 AuthenticateAsync:
protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { // 解析二维码 var result = await EnsureCookieTicket(); if (!result.Succeeded) { return result; } // 从二维码中拿当事人信息进行验证 var context = new CookieValidatePrincipalContext(Context, result.Ticket, Options); await Options.Events.ValidatePrincipal(context); if (context.Principal == null) { return AuthenticateResult.Fail("No principal."); } if (context.ShouldRenew) { RequestRefresh(result.Ticket); } // 验讫, 写入芯片 return AuthenticateResult.Success(new AuthenticationTicket(context.Principal, context.Properties, Options.AuthenticationScheme)); }
HandleSignInAsync
我们故事继续……
奥巴马检票完成之后,把票就交给了小李,小李拿到票之后,导演又喊了一声:“ cut ”……