using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WMS.Web.Core.Dto.Login; using WMS.Web.Domain.IService.Public; using WMS.Web.Domain.Services.Public; namespace WMS.Web.Repositories.DependencyInjection { /// /// token 黑名单中间件 /// public class AuthorizationTokenSecurityPolicy { private readonly RequestDelegate _next; private readonly IMemoryCache _cache; private ILogger _logger; private DateTime _refreshTime = DateTime.Now.AddYears(-5); private readonly RedisClientService _redisClientService; /// /// token黑名单中间件 /// /// /// public AuthorizationTokenSecurityPolicy(RequestDelegate next, ILogger logger, IMemoryCache cache, RedisClientService redisClientService) { _next = next; _cache = cache; this._logger = logger; _redisClientService = redisClientService; } /// /// 事件 /// /// /// public async Task Invoke(HttpContext context, ILoginService loginService) { string authorization = context.Request.Headers["Authorization"]; string path = context.Request.Path.Value.ToLower(); string[] pathlist = path.Split('/'); bool isLogin = pathlist.Where(x => x == "login" || x.ToLower() == "heart" || x.ToLower() == "test").Any(); if (isLogin) { context.Response.StatusCode = 200; await _next(context); return; } if (string.IsNullOrEmpty(authorization)) { context.Response.StatusCode = 401; var result = JsonConvert.SerializeObject(new { status = 401, data = string.Empty, message = "授权失败,请重新登录" }); context.Response.ContentType = "application/json;charset=utf-8"; await context.Response.WriteAsync(result); return; } else { string token = string.Empty; if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { token = authorization.Substring("Bearer ".Length).Trim(); } //判断前端过来的token if (string.IsNullOrEmpty(token)) { context.Response.StatusCode = 401; var result = JsonConvert.SerializeObject(new { status = 401, data = string.Empty, message = "授权失败,请重新登录" }); context.Response.ContentType = "application/json;charset=utf-8"; await context.Response.WriteAsync(result); return; } //1.验证是否有登录数据缓存 var logininfo = _redisClientService.GetStringKey($"wms_login_{token}"); if (logininfo == null) { context.Response.StatusCode = 401; var result = JsonConvert.SerializeObject(new { status = 401, data = string.Empty, message = "授权失败,请重新登录" }); context.Response.ContentType = "application/json;charset=utf-8"; await context.Response.WriteAsync(result); return; } else { _logger.LogInformation("RefreshToken:我在刷新登录--1"+ logininfo.TokenInfo.Expired.ToString()); //2.判断缓存的token 过期时间 if (!string.IsNullOrEmpty(logininfo.TokenInfo.Token) && logininfo.TokenInfo.Expired.AddMinutes(-10) <= DateTime.Now) { _logger.LogInformation("RefreshToken:我在刷新登录--2"); var refreshtokeninfo = RefreshToken(logininfo.TokenInfo.Token, logininfo.TokenInfo.RefreshToken, loginService); var info = _redisClientService.GetStringKey($"wms_login_{token}"); _logger.LogInformation("RefreshToken:我在刷新登录--完成:" + info.UserInfo.Nickname); //刷新token后不能删除_redis用户缓存 //if (!refreshtokeninfo) //{ // RemoveRedisLoginInfo(token); //} } //3.验证检查是否有黑名单的token缓存 string blacktoken = _redisClientService.GetStringKey($"wms_black_token_{logininfo.UserInfo.UcId}"); if (string.IsNullOrEmpty(blacktoken)) { context.Response.StatusCode = 200; await _next(context); } else { RemoveRedisLoginInfo(token); context.Response.StatusCode = 403; var result = JsonConvert.SerializeObject(new { status = 403, data = string.Empty, message = "拒绝用户证书试图访问此web站点,请与站点管理员联系以建立用户证书权限" }); context.Response.ContentType = "application/json;charset=utf-8"; await context.Response.WriteAsync(result); } } if (context.Response.StatusCode == 401 || context.Response.StatusCode == 403) { //调用单点的退出接口 var dto = new LoginOutDto() { UcId = logininfo.UserInfo.UcId.ToString(), SessionId = logininfo.UserInfo.SeesionId, Token = logininfo.TokenInfo.Token, AccessToken = logininfo.TokenInfo.PhpToken, ExpiresIn = logininfo.TokenInfo.Expired }; var res = await loginService.LoginOutAsync(dto); return; } } } /// /// 过期,或者失效,移出token /// /// private void RemoveRedisLoginInfo(string token) { if (!string.IsNullOrEmpty(token)) { var info = _redisClientService.GetStringKey($"wms_login_{token}"); if (info != null) { _redisClientService.RemoveStringKey($"wms_login_{token}"); } } } /// /// 刷新token /// /// /// private bool RefreshToken(string OldToken, string RefreshToken, ILoginService _loginService) { _logger.LogInformation("RefreshToken:我在刷新登录--3"); var res = _loginService.RefreshToken(OldToken, RefreshToken); if (!res.Result.Success) return false; else return true; } } }