.NET CORE单用户登录
以JWT认证为例,核心思路是将用户最后一次登录的jwt信息缓存起来,每一次收到请求,都将当前jwt和缓存的jwt进行对比,如果对比结果不一致,则代表当前用户在别处登录了。
新建过滤器
/// <summary> /// 单用户登录过滤器 /// </summary> public class JwtAuthorizeFilter : IAuthorizationFilter { private readonly IMemoryCache _memoryCache; public JwtAuthorizeFilter(IMemoryCache memoryCache) { _memoryCache = memoryCache; } public void OnAuthorization(AuthorizationFilterContext context) { try { if (context.Filters.Contains(new NoAuthenticationAttribute()) || context.Filters.Any(item => item is IAllowAnonymousFilter)) //拥有指定过滤器或者AllowAnonymous特性的请求不处理 { return; } var token = context.HttpContext.Request.Headers["Authorization"].FirstOrDefault(); if (string.IsNullOrWhiteSpace(token)) { context.Result = new JsonResult(new ApiResultContent(false) { message = ApiResultStateCode.invalid_credentials }); return; } var jwt = token.Split(" ")[1]; var tokenObj = new JwtSecurityToken(jwt); var claimsIdentity = new ClaimsIdentity(tokenObj.Claims); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); var userid = claimsPrincipal?.Claims.FirstOrDefault(c => c.Type == "id")?.Value; //登录时存入claims的用户唯一标识 var mJwt = _memoryCache.Get<string>("user" + userid); if (mJwt != jwt) { context.Result = new UnauthorizedObjectResult("当前用户在别处登录"); return; } } catch (Exception ex) { context.Result = new UnauthorizedObjectResult("身份认证不通过"); return; } } }
在startup.cs文件处注册这个过滤器(.NET 3以下使用AddMvc)
services.AddControllers(o => { o.Filters.Add<JwtAuthorizeFilter>(); })
新建过滤器,将其以特性的方式增加到登录接口处(或者直接使用[AllowAnonymous])
/// <summary> /// 拥有此特性,不进行单用户登录的验证 /// </summary> public class NoAuthenticationAttribute: Attribute, IFilterMetadata { }