Files
WMS-Api/src/WMS.Web.Repositories/DependencyInjection/AuthorizationTokenSecurityPolicy.cs
2023-12-08 17:09:55 +08:00

179 lines
7.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
{
/// <summary>
/// token 黑名单中间件
/// </summary>
public class AuthorizationTokenSecurityPolicy
{
private readonly RequestDelegate _next;
private readonly IMemoryCache _cache;
private ILogger<AuthorizationTokenSecurityPolicy> _logger;
private DateTime _refreshTime = DateTime.Now.AddYears(-5);
private readonly RedisClientService _redisClientService;
/// <summary>
/// token黑名单中间件
/// </summary>
/// <param name="next"></param>
/// <param name="cache"></param>
public AuthorizationTokenSecurityPolicy(RequestDelegate next, ILogger<AuthorizationTokenSecurityPolicy> logger, IMemoryCache cache, RedisClientService redisClientService)
{
_next = next;
_cache = cache;
this._logger = logger;
_redisClientService = redisClientService;
}
/// <summary>
/// 事件
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
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<LoginInDto>($"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<LoginInDto>($"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;
}
}
}
/// <summary>
/// 过期或者失效移出token
/// </summary>
/// <param name="token"></param>
private void RemoveRedisLoginInfo(string token)
{
if (!string.IsNullOrEmpty(token))
{
var info = _redisClientService.GetStringKey<LoginInDto>($"wms_login_{token}");
if (info != null)
{
_redisClientService.RemoveStringKey($"wms_login_{token}");
}
}
}
/// <summary>
/// 刷新token
/// </summary>
/// <param name="RefreshToken"></param>
/// <returns></returns>
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;
}
}
}