如何将控制器[AuthenticateJWT]的JWT认证逻辑应用至中间件方法?
在ASP.NET Core中间件中实现JWT令牌验证
要把控制器级别的JWT认证改成中间件级别的全局(或指定路由)验证,你可以按以下步骤实现:
1. 创建自定义JWT验证中间件
这个中间件会拦截请求,提取并验证JWT令牌,验证通过后才允许请求继续流转到后续中间件或控制器。
using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; public class JwtValidationMiddleware { private readonly RequestDelegate _next; private readonly IConfiguration _config; public JwtValidationMiddleware(RequestDelegate next, IConfiguration config) { _next = next; _config = config; } public async Task InvokeAsync(HttpContext context) { // 从请求头获取Bearer令牌 var authHeader = context.Request.Headers["Authorization"].FirstOrDefault(); if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; await context.Response.WriteAsync("未提供有效身份凭证"); return; } var token = authHeader["Bearer ".Length..].Trim(); var validationParams = new TokenValidationParameters { // 根据你的业务需求调整验证规则 ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = _config["Jwt:Issuer"], ValidAudience = _config["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:SecretKey"])), // 允许一定的时间偏差,避免因服务器时间不同导致的验证失败 ClockSkew = TimeSpan.FromSeconds(30) }; try { // 验证令牌并生成ClaimsPrincipal var tokenHandler = new JwtSecurityTokenHandler(); var claimsPrincipal = tokenHandler.ValidateToken(token, validationParams, out _); // 将验证后的用户信息注入到HttpContext,供后续逻辑使用 context.User = claimsPrincipal; // 继续执行后续中间件/控制器逻辑 await _next(context); } catch (SecurityTokenExpiredException) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; await context.Response.WriteAsync("令牌已过期"); } catch (SecurityTokenInvalidSignatureException) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; await context.Response.WriteAsync("令牌签名无效"); } catch (Exception ex) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; await context.Response.WriteAsync($"令牌验证失败: {ex.Message}"); } } }
2. 编写中间件扩展方法
为了方便在管道中注册中间件,创建一个扩展方法:
public static class JwtMiddlewareExtensions { public static IApplicationBuilder UseJwtValidation(this IApplicationBuilder app) { return app.UseMiddleware<JwtValidationMiddleware>(); } }
3. 将中间件注册到请求管道
在Program.cs中,把自定义JWT中间件添加到管道中,注意顺序要放在路由和端点之前,确保所有请求先经过验证:
var builder = WebApplication.CreateBuilder(args); // 添加必要服务(如果需要使用ASP.NET Core认证体系相关功能) builder.Services.AddAuthentication(); var app = builder.Build(); // 注册自定义JWT验证中间件 app.UseJwtValidation(); // 路由和端点配置 app.UseRouting(); app.MapControllers(); app.Run();
4. 可选:指定需要验证的路由范围
如果不需要对所有请求验证,只针对特定路由(比如/api开头的接口),可以在中间件的InvokeAsync方法开头添加路由判断:
// 仅对/api开头的路由进行JWT验证 if (!context.Request.Path.StartsWithSegments("/api", StringComparison.OrdinalIgnoreCase)) { await _next(context); return; }
5. 清理控制器上的特性
现在中间件已经接管了JWT验证,你可以移除控制器类上的[AuthenticateJWT]特性。
配置说明
确保你的appsettings.json中包含JWT的必要配置:
{ "Jwt": { "Issuer": "your-issuer", "Audience": "your-audience", "SecretKey": "your-strong-secret-key-at-least-16-characters" } }
内容的提问来源于stack exchange,提问作者fozail akram
相关产品推荐
相关产品推荐

