1. 新增API版本枚举SDK项,创建SDK基础控制器 2. 添加IList、string扩展方法,新增时间戳扩展工具 3. 新增OSS配置、STS凭证服务、文件处理相关代码 4. 重构Redis缓存组件,替换StackExchange.Redis为CSRedisCore 5. 修复原有Redis操作方法调用,新增基础控制器快捷返回方法 6. 新增阿里云OSS、短信、VOD相关SDK依赖 7. 配置阿里云OSS相关参数到appsettings
79 lines
2.7 KiB
C#
79 lines
2.7 KiB
C#
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Configuration;
|
|
using QYZH.InteractiveMagazine.Models.Settings;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
|
|
namespace QYZH.InteractiveMagazine.Infrastructure.Middleware;
|
|
|
|
public class JwtAutoRefreshMiddleware
|
|
{
|
|
private readonly RequestDelegate _next;
|
|
private readonly IConfiguration _configuration;
|
|
private const string TokenKeyPrefix = "InteractiveMagazine:AdminAuth:Token";
|
|
private const int RefreshThresholdMinutes = 10;
|
|
|
|
public JwtAutoRefreshMiddleware(RequestDelegate next, IConfiguration configuration)
|
|
{
|
|
_next = next;
|
|
_configuration = configuration;
|
|
}
|
|
|
|
public async Task InvokeAsync(HttpContext context)
|
|
{
|
|
var authHeader = context.Request.Headers.Authorization.FirstOrDefault();
|
|
if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer "))
|
|
{
|
|
var token = authHeader.Substring("Bearer ".Length).Trim();
|
|
await TryAutoRefreshTokenAsync(context, token);
|
|
}
|
|
|
|
await _next(context);
|
|
}
|
|
|
|
private async Task TryAutoRefreshTokenAsync(HttpContext context, string token)
|
|
{
|
|
try
|
|
{
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
if (tokenHandler.ReadToken(token) is not JwtSecurityToken jwtToken)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var expiryTime = jwtToken.ValidTo;
|
|
var remainingTime = expiryTime - DateTime.Now;
|
|
|
|
if (remainingTime <= TimeSpan.FromMinutes(RefreshThresholdMinutes) && remainingTime > TimeSpan.Zero)
|
|
{
|
|
var userId = jwtToken.Claims.FirstOrDefault(c => c.Type == System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
|
|
var userName = jwtToken.Claims.FirstOrDefault(c => c.Type == System.Security.Claims.ClaimTypes.Name)?.Value;
|
|
|
|
if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(userName))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var jwtSettings = _configuration.GetSection("JwtSettings").Get<JwtSettings>();
|
|
if (jwtSettings == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var newToken = QYZH.InteractiveMagazine.Infrastructure.Auth.JwtHelper.GenerateToken(
|
|
long.Parse(userId), userName, jwtSettings);
|
|
|
|
await RedisHelper.SetAsync(
|
|
$"{TokenKeyPrefix}:{userId}",
|
|
newToken,
|
|
TimeSpan.FromMinutes(jwtSettings.ExpiryMinutes));
|
|
|
|
context.Response.Headers["X-New-Token"] = newToken;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// 忽略自动刷新异常,由后续认证中间件处理
|
|
}
|
|
}
|
|
}
|