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));
}
}
}
}