using Infrastructure; using Infrastructure.Model; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System.Security.Claims; using ZR.Common; namespace ZR.ServiceCore.Middleware { /// /// jwt认证中间件 /// public class JwtAuthMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; private static readonly string[] _whitelistPaths = new[] { ".png", "/msgHub" }; public JwtAuthMiddleware(RequestDelegate next, ILogger logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext context) { var path = context.Request.Path.Value; // 如果请求是带扩展名的(即包含 .) if (path.Contains('.')) { await _next(context); return; } if (_whitelistPaths.Any(p => path.StartsWith(p, StringComparison.OrdinalIgnoreCase))) { await _next(context); return; } var endpoint = context.GetEndpoint(); var allowAnonymous = endpoint?.Metadata?.GetMetadata() != null; if (allowAnonymous) { await _next(context); return; } string ip = HttpContextExtension.GetClientUserIp(context); string url = context.Request.Path; string osType = context.Request.Headers["os"]; TokenModel loginUser = JwtUtil.GetLoginUser(context); if (loginUser != null) { var now = DateTime.UtcNow; var ts = loginUser.ExpireTime - now; var cacheKey = $"token_{loginUser.UserId}"; if (!CacheHelper.Exists(cacheKey) && ts.TotalMinutes < 5 && ts.TotalMinutes > 0) { var newToken = JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(loginUser)); CacheHelper.SetCache(cacheKey, cacheKey, 1); if (!string.IsNullOrEmpty(osType)) { context.Response.Headers.Append("Access-Control-Expose-Headers", "X-Refresh-Token"); } context.Response.Headers.Append("X-Refresh-Token", newToken); _logger.LogInformation($"刷新Token: {loginUser.UserName}"); } // 还可以挂载到 context.User var identity = new ClaimsIdentity(JwtUtil.AddClaims(loginUser), "jwt"); context.User = new ClaimsPrincipal(identity); await _next(context); } else { string msg = $"请求访问[{url}]失败,Token无效或未登录"; _logger.LogWarning(msg); //context.Response.StatusCode = StatusCodes.Status401Unauthorized; await context.Response.WriteAsJsonAsync(ApiResult.Error(ResultCode.DENY, msg)); } } } }