ASP.NET Core 认证与授权[2]:Cookie认证 (7)

在Cookie认证的配置中,提供了一系列的事件,其中便有一个OnValidatePrincipal事件,用来附加服务端的验证逻辑:

.AddCookie(options => { options.Events = new CookieAuthenticationEvents { OnValidatePrincipal = LastChangedValidator.ValidateAsync }; });

如上,便完成了该事件的注册,不过该验证通常会查询数据库,损耗较大,可以通过设置验证周期来提高性能,如:每5分钟执行验证一次(在MVC5中是有该配置的,Core中暂未发现)。

Persistent and ExpiresUtc

对于Cookie来说,默认的过期时间为Session,即关闭浏览器后就清除。通常在用户登录时会提供一个记住我的选项,用来保证在关闭浏览时不清除Cookie。而在SignInAsync方法中,还接收一个AuthenticationProperties类型的参数,可以用来指定Cookie是否持久化以及过期时间:

await HttpContext.SignInAsync("MyCookieAuthenticationScheme", principal, new AuthenticationProperties { // 持久保存 IsPersistent = true // 指定过期时间 ExpiresUtc = DateTime.UtcNow.AddMinutes(20) });

看一下CookieAuthenticationHandler中SignInAsync方法关于该配置的实现:

if (!signInContext.Properties.ExpiresUtc.HasValue) { signInContext.Properties.ExpiresUtc = issuedUtc.Add(Options.ExpireTimeSpan); } if (signInContext.Properties.IsPersistent) { var expiresUtc = signInContext.Properties.ExpiresUtc ?? issuedUtc.Add(Options.ExpireTimeSpan); signInContext.CookieOptions.Expires = expiresUtc.ToUniversalTime(); }

只有在IsPersistent为True时,才会在写入Cookie指定Expires。需要注意的是浏览器中的Cookie过期时间仅仅是用来指定浏览器是否删除Cookie,而在Cookie存储的值中,也会包含该Cookie认证的发布时间和过期时间等,并在HandleAuthenticateAsync方法中对会其进行验证,并不是说只要你有Cookie就能验证通过。

源码解析 AddCookie

AddCookie已多次用过,无需多说,直接看源码:

public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder) => builder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, null, null); public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<CookieAuthenticationOptions> configureOptions) { builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>()); return builder.AddScheme<CookieAuthenticationOptions, CookieAuthenticationHandler>(authenticationScheme, displayName, configureOptions); }

其实现非常简单,首先注册了Cookie认证的配置项CookieAuthenticationOptions,而authenticationScheme参数用来指定当前认证的唯一的标识,不能重复。通常,使用默认的CookieAuthenticationDefaults.AuthenticationScheme就可以了,但是当我们同时使用多个Cookie认证方式时,需要手动为他们指定不同的Scheme。

最后,直接调用上一章中介绍的AddScheme,完成对CookieAuthenticationHandler的注册。

CookieAuthenticationOptions

CookieAuthenticationOptions是针对Cookie认证的各种配置,如重定向地址,认证阶段事件的注册,Cookie名,过期时间等等,首先看一下它的定义:

public class CookieAuthenticationOptions : AuthenticationSchemeOptions { private CookieBuilder _cookieBuilder = new RequestPathBaseCookieBuilder { SameSite = SameSiteMode.Lax, HttpOnly = true, SecurePolicy = CookieSecurePolicy.SameAsRequest, }; public CookieAuthenticationOptions() { ExpireTimeSpan = TimeSpan.FromDays(14); ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter; SlidingExpiration = true; Events = new CookieAuthenticationEvents(); } public CookieBuilder Cookie { get => _cookieBuilder; set => _cookieBuilder = value ?? throw new ArgumentNullException(nameof(value)); } public new CookieAuthenticationEvents Events { get => (CookieAuthenticationEvents)base.Events; set => base.Events = value; } public ITicketStore SessionStore { get; set; } // 当用户未登录时,重定向到该路径,默认:/Account/Login public PathString LoginPath { get; set; } // 指定登出的路径,默认:/Account/Logout public PathString LogoutPath { get; set; } // 当用户无权访问时,重定向到该路径,默认:/Account/AccessDenied public PathString AccessDeniedPath { get; set; } // 返回地址参数名,默认:ReturnUrl public string ReturnUrlParameter { get; set; } // 指定Cookie的过期时间 public TimeSpan ExpireTimeSpan { get; set; } // 当Cookie过期时间已达一半时,是否重置为ExpireTimeSpan public bool SlidingExpiration { get; set; } // 用来将Cookie写入到浏览器或删除 public ICookieManager CookieManager { get; set; } public IDataProtectionProvider DataProtectionProvider { get; set; } public ISecureDataFormat<AuthenticationTicket> TicketDataFormat { get; set; } } CookieBuilder

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwjjjf.html