AspNetCore.Identity是.Net Core自带的用户管理模块,功能丰富,用起来也是非常方便的,但是在使用的过程中发现它无法控制是否需要颁发登录的Session,由于业务中使用的是JWT登录验证授权,我是不需要AspNetCore.Identity去发布Session的,然后就自己去看了.Net Core源码,发现SignInManager类的方法大部分都是虚方法,所以就自己写了个派生类使用。
先看一下AspNetCore.Identity的登录验证流程的源码
1、这个方法要传入用户名 userName、用户密码 password、是否保存登录状态(浏览器关掉了Session是否还有用)isPersistent,登录失败多少次锁定 lockoutOnFailure
2、这个方法主要是检查用户账号密码以及登录失败处理的,最后去双因素身份验证的,需要传入一个用户实体 user,其他参数与第一个方法一致,CheckPasswordSignInAsync方法主要是验证用户信息,不涉及颁发Session,先跳过
3、双因素身份验证方法,需要传入用户实体 user、是否保存登录状态 isPersistent、要使用的第三方登录程序 loginProvider、是否需要双因素身份验证 bypassTwoFactor。
4、下面方法主要是前往签名颁发Seesion,传入的参数前面已经解释过了,在签名颁发Session是就可以阻止它了,不需要返回值。从这一步以后其实可以不看了,但是还是要了解了解的。
5、这个就是上个方法中上下文Context.SignInAsync() 方法了,调用 IAuthenticationService 类的 SignInAsyc 方法
6、这个方法主要是做一下数据验证判断,handler是类 IAuthenticationHandler
6、主要是判断用户登录方法是否修改,修改了就去重新登录,应该是使用Cookies登录时调用的
7、最后就是对设置Cookies和Seesion了,以及对Cookies信息进行加密,太长了,分开截屏吧
我需要的是不让AspNetCore.Identity去颁发Session,所以需要修改第四步中的方法,其实很简单
1 //public class MySignInManager<TUser> : SignInManager<TUser> where TUser : class 2 public class MySignInManager : SignInManager<ApplicationUser> 3 { 4 private const string HeaderValueNoCache = "no-cache"; 5 private const string HeaderValueEpocDate = "Thu, 01 Jan 1970 00:00:00 GMT"; 6 7 public MySignInManager(UserManager<ApplicationUser> userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor, ILogger<SignInManager<ApplicationUser>> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation<ApplicationUser> confirmation) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) 8 { 9 } 10 /// <summary> 11 /// Signs in the specified <paramref name="user"/>. 12 /// </summary> 13 /// <param name="user">The user to sign-in.</param> 14 /// <param name="authenticationProperties">Properties applied to the login and authentication cookie.</param> 15 /// <param name="additionalClaims">Additional claims that will be stored in the cookie.</param> 16 /// <returns>The task object representing the asynchronous operation.</returns> 17 public override async Task SignInWithClaimsAsync(ApplicationUser user, AuthenticationProperties authenticationProperties, IEnumerable<Claim> additionalClaims) 18 { 19 Context.Response.Headers[HeaderNames.CacheControl] = HeaderValueNoCache; 20 Context.Response.Headers[HeaderNames.Pragma] = HeaderValueNoCache; 21 Context.Response.Headers[HeaderNames.Expires] = HeaderValueEpocDate; 22 await Task.CompletedTask; 23 } 24 }
然后再Startup文件中注入服务依赖
1 services.TryAddScoped<MySignInManager>();
登录的类中把SignInManager改成MySignInManager就行了
1 private readonly IConfiguration _configuration; 2 private readonly UserManager<ApplicationUser> _userManager; 3 private readonly MySignInManager _signInManager; 4 5 public AuthenticateController(IConfiguration configuration, UserManager<ApplicationUser> userManager, MySignInManager signInManager) 6 { 7 _configuration = configuration; 8 _userManager = userManager; 9 _signInManager = signInManager; 10 }
参考资料:https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.authentication?view=aspnetcore-6.0