我将从CookieAuthenticationMiddleware中间件的使用,来讲述cookie认证是如何实现的
1、系统是如何调用CookieAuthenticationMiddleware的
在web.config的appSettings里添加
public class IdentityConfig
{
public void Configuration(IAppBuilder app)
{
// 默认使用CookieAuthenticationMiddleware
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});
}
}
在CookieAuthenticationExtensions里定义了默认的cookieAuthentication中间件
public static IAppBuilder UseCookieAuthentication(this IAppBuilder app, CookieAuthenticationOptions options, PipelineStage stage)
{
if (app == null)
{
throw new ArgumentNullException("app");
}
// 默认中间件
app.Use(typeof(CookieAuthenticationMiddleware), app, options);
app.UseStageMarker(stage);
return app;
}
2、主要class说明
CookieAuthenticationMiddleware:项目使用时调用的验证中间件类,下面简称 【cookieAuth中间件类】
AuthenticationMiddleware:CookieAuthenticationMiddleware的父类,下面简称 【Auth中间件类】
---下面说的是重点,实际的工作处理者--------
CookieAuthenticationHandler:【cookieAuth处理类】
AuthenticationHandler:泛型抽象类,主要有个方法Initialize。是CookieAuthenticationHandler的父类,下面简称 【Auth处理子类】。
AuthenticationHandler:抽象类,主要有BaseInitializeAsync和TeardownAsync方法,是AuthenticationHandler的父类,下面简称 【Auth处理基类】。
3、代码功能说明
public abstract class AuthenticationMiddleware : OwinMiddleware where TOptions : AuthenticationOptions
{
protected AuthenticationMiddleware(OwinMiddleware next, TOptions options) : base(next)
{
if (options == null)
{
throw new ArgumentNullException("options");
}
Options = options;
}
public TOptions Options { get; set; }
// 具体的执行流程很简单,分为创建,初始化,下一个中间件执行,卸载
public override async Task Invoke(IOwinContext context)
{
//获取处理者,【cookieAuth处理类】
AuthenticationHandler handler = CreateHandler();
//初始化,会调用【Auth处理基类】的BaseInitializeAsync,具体查看---Initialize说明---
await handler.Initialize(Options, context);
if (!await handler.InvokeAsync())//默认返回false
{
//调用下一个中间件,比方说调用MVC中间件
await Next.Invoke(context);
}
// 最后执行,会调用【Auth处理基类】的TeardownAsync,具体说明查看---Teardown说明---
await handler.TeardownAsync();
}
protected abstract AuthenticationHandler CreateHandler();
}
---Initialize说明---
初始化的时候,将获取已有的ticket,供后续的中间件使用
将调用【Auth处理基类】的BaseInitializeAsync来完成初始化
protected async Task BaseInitializeAsync(AuthenticationOptions options, IOwinContext context)
{
_baseOptions = options;
Context = context;
Helper = new SecurityHelper(context);
RequestPathBase = Request.PathBase;
_registration = Request.RegisterAuthenticationHandler(this);
// 设置响应事件,在teardown之后会执行
Response.OnSendingHeaders(OnSendingHeaderCallback, this);
await InitializeCoreAsync();
// 主动模式时执行
if (BaseOptions.AuthenticationMode == AuthenticationMode.Active)
{
// 根据cookie得到ticket,判断是否需要renew,后续的中间件可以获取identity信息
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket != null && ticket.Identity != null)
{
// 将identity添加到context.Request.User里
Helper.AddUserIdentity(ticket.Identity);
}
}
}
---Teardown说明---
就是判断是否是登录,注销,renew,然后处理
登录:制作ticket写入cookie
注销:删除cookie
renew(剩余时长<使用时长):重新生成cookie的有效期
internal async Task TeardownAsync()
{
// 申请响应
// 判断是否是登录(IAuthenticationManager.SignIn),注销(IAuthenticationManager.SignOut),renew(_shouldRenew标志),然后处理
await ApplyResponseAsync();
// 默认返回null
await TeardownCoreAsync();
// request[key:Constants.SecurityAuthenticate],注销AuthenticationHandler,恢复成RegisterAuthenticationHandler之前的状态
Request.UnregisterAuthenticationHandler(_registration);
}
大致的流程就是这样,具体的如何判断登录,注销,下一章再详细讲解。