You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将控制器[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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 23:15:33