fix 登录授权的问题
This commit is contained in:
@ -3,21 +3,17 @@ using Microsoft.Extensions.Configuration;
|
||||
using QYZH.InteractiveMagazine.Infrastructure.Auth;
|
||||
using QYZH.InteractiveMagazine.Models.Settings;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace QYZH.InteractiveMagazine.Infrastructure.Middleware;
|
||||
|
||||
/// <summary>
|
||||
/// JWT 自动刷新中间件
|
||||
/// 功能:
|
||||
/// 每次请求都刷新 Redis 中 Token 的过期时间(保持会话活跃)
|
||||
/// 前端永远使用同一个 Token,无需处理 Token 刷新
|
||||
/// Refreshes the Redis session TTL for the current JWT when it is still the active token.
|
||||
/// </summary>
|
||||
public class JwtAutoRefreshMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IConfiguration _configuration;
|
||||
private const string AdminTokenKeyPrefix = "InteractiveMagazine:AdminAuth:Token";
|
||||
private const string WeChatTokenKeyPrefix = "InteractiveMagazine:WeChatAuth:Token";
|
||||
|
||||
public JwtAutoRefreshMiddleware(RequestDelegate next, IConfiguration configuration)
|
||||
{
|
||||
@ -31,13 +27,13 @@ public class JwtAutoRefreshMiddleware
|
||||
if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer "))
|
||||
{
|
||||
var token = authHeader.Substring("Bearer ".Length).Trim();
|
||||
await TryRefreshRedisTokenExpiryAsync(context, token);
|
||||
await TryRefreshRedisTokenExpiryAsync(token);
|
||||
}
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
|
||||
private async Task TryRefreshRedisTokenExpiryAsync(HttpContext context, string token)
|
||||
private async Task TryRefreshRedisTokenExpiryAsync(string token)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -47,60 +43,57 @@ public class JwtAutoRefreshMiddleware
|
||||
return;
|
||||
}
|
||||
|
||||
var expiryTime = jwtToken.ValidTo;
|
||||
var remainingTime = expiryTime - DateTime.Now;
|
||||
|
||||
// JWT 已过期,不处理
|
||||
if (remainingTime <= TimeSpan.Zero)
|
||||
if (jwtToken.ValidTo <= DateTime.UtcNow)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var userId = jwtToken.Claims.FirstOrDefault(c => c.Type == System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
|
||||
var userId = GetClaimValue(jwtToken, ClaimTypes.NameIdentifier, JwtRegisteredClaimNames.NameId);
|
||||
if (string.IsNullOrEmpty(userId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var wxUserId = jwtToken.Claims.FirstOrDefault(c => c.Type == JwtHelper.WxUserIdClaimType)?.Value;
|
||||
if (string.IsNullOrEmpty(wxUserId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var jwtSettings = _configuration.GetSection("JwtSettings").Get<JwtSettings>();
|
||||
if (jwtSettings == null || jwtSettings.ExpiryMinutes <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 每次请求都刷新 Redis 中 Token 的过期时间
|
||||
await RefreshRedisTokenExpiryAsync(wxUserId,userId, token, jwtSettings.ExpiryMinutes);
|
||||
var wxUserId = GetClaimValue(jwtToken, JwtHelper.WxUserIdClaimType);
|
||||
await RefreshRedisTokenExpiryAsync(wxUserId, userId, token, jwtSettings.ExpiryMinutes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 忽略自动刷新异常,由后续认证中间件处理
|
||||
// Ignore refresh failures. Authentication middleware will validate the request later.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新 Redis 中已存在 Token 的过期时间(保持会话活跃)
|
||||
/// </summary>
|
||||
private async Task RefreshRedisTokenExpiryAsync(string wxUserId,string userId, string currentToken, int expiryMinutes)
|
||||
private static async Task RefreshRedisTokenExpiryAsync(string? wxUserId, string userId, string currentToken, int expiryMinutes)
|
||||
{
|
||||
// 检查 Admin Token
|
||||
var adminTokenKey = $"{AdminTokenKeyPrefix}:{userId}";
|
||||
var adminTokenKey = JwtHelper.BuildAdminTokenKey(userId);
|
||||
var adminToken = await RedisHelper.GetAsync(adminTokenKey);
|
||||
if (!string.IsNullOrEmpty(adminToken))
|
||||
if (string.IsNullOrEmpty(wxUserId) && !string.IsNullOrEmpty(adminToken))
|
||||
{
|
||||
await RedisHelper.SetAsync(adminTokenKey, currentToken, TimeSpan.FromMinutes(expiryMinutes));
|
||||
await RedisHelper.SetAsync(adminTokenKey, adminToken, TimeSpan.FromMinutes(expiryMinutes));
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查 WeChat Token
|
||||
var wechatTokenKey = $"{WeChatTokenKeyPrefix}:{wxUserId}{userId}";
|
||||
if (string.IsNullOrEmpty(wxUserId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var wechatTokenKey = JwtHelper.BuildWeChatTokenKey(wxUserId, userId);
|
||||
var wechatToken = await RedisHelper.GetAsync(wechatTokenKey);
|
||||
if (!string.IsNullOrEmpty(wechatToken))
|
||||
if (wechatToken == currentToken)
|
||||
{
|
||||
await RedisHelper.SetAsync(wechatTokenKey, currentToken, TimeSpan.FromMinutes(expiryMinutes));
|
||||
}
|
||||
}
|
||||
|
||||
private static string? GetClaimValue(JwtSecurityToken jwtToken, params string[] claimTypes)
|
||||
{
|
||||
return jwtToken.Claims.FirstOrDefault(c => claimTypes.Contains(c.Type))?.Value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user