ASP.NET Core 中间件:解析 JWT 并注入用户上下文的最佳实践

ASP.NET Core 中,可以通过自定义中间件解析 JWT 并将用户信息提取到HttpContext 的用户上下文中(如HttpContext.User),以便在后续的处理中使用这些信息(如授权、日志记录等)。以下是实现步骤和完整示例:


1. 背景

JWT(JSON Web Token)是一种广泛使用的身份验证机制。一般情况下,JWT 会包含在 HTTP 请求的Authorization 头部中,格式如下:

Authorization: Bearer <token>

我们需要在中间件中:

  1. 从请求头中提取 JWT。
  2. 验证 JWT 的合法性(如签名、过期时间)。
  3. 将解析出的用户信息(如Claims)注入到HttpContext.User

2. 实现步骤

步骤 1:添加依赖包

使用Microsoft.AspNetCore.Authentication.JwtBearer 处理 JWT 验证。

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

步骤 2:配置 JWT 参数

appsettings.json 或代码中配置 JWT 的密钥、颁发者和受众等信息。

appsettings.json 示例:

{
  "JwtSettings": {
    "Issuer": "your-issuer",
    "Audience": "your-audience",
    "SecretKey": "your-secret-key"
  }
}

步骤 3:创建 JWT 中间件

以下是一个自定义中间件的实现:

using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

publicclassJwtMiddleware
{
    privatereadonly RequestDelegate _next;
    privatereadonlystring _secretKey;
    privatereadonlystring _issuer;
    privatereadonlystring _audience;

    public JwtMiddleware(RequestDelegate next, IConfiguration configuration)
    {
        _next = next;
        var jwtSettings = configuration.GetSection("JwtSettings");
        _secretKey = jwtSettings["SecretKey"];
        _issuer = jwtSettings["Issuer"];
        _audience = jwtSettings["Audience"];
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();

        if (!string.IsNullOrEmpty(token))
        {
            AttachUserToContext(context, token);
        }

        // 调用下一个中间件
        await _next(context);
    }

    private void AttachUserToContext(HttpContext context, string token)
    {
        try
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.UTF8.GetBytes(_secretKey);

            // 验证令牌
            var validationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = _issuer,
                ValidAudience = _audience,
                IssuerSigningKey = new SymmetricSecurityKey(key)
            };

            var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);

            // 将用户信息注入 HttpContext.User
            context.User = principal;
        }
        catch (Exception ex)
        {
            // 如果令牌无效,忽略错误并不设置 HttpContext.User
            Console.WriteLine($"JWT validation failed: {ex.Message}");
        }
    }
}

步骤 4:注册中间件

Startup.cs 或Program.cs 中注册自定义中间件。

public classStartup
{
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseMiddleware<JwtMiddleware>();

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

3. 测试流程

请求头中带有有效的 JWT

假设 JWT 的Claims 中包含以下信息:

{
  "sub": "1234567890",
  "name": "John Doe",
  "role": "Admin"
}

通过JwtMiddleware 验证后,HttpContext.User 会包含这些 Claims,可以在控制器或其他中间件中通过以下方式访问:

[HttpGet("test")]
public IActionResult Test()
{
    var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); // 1234567890
    var userName = User.Identity.Name; // John Doe
    var userRole = User.FindFirstValue(ClaimTypes.Role); // Admin

    return Ok(new { userId, userName, userRole });
}

请求头中没有 JWT 或 JWT 无效

  • 如果请求头中不包含 JWT,中间件将跳过用户上下文的设置,HttpContext.User 为匿名用户。
  • 如果 JWT 无效(如签名错误、过期等),中间件会捕获异常,并保持HttpContext.User 为匿名用户。

4. JWT 中间件的应用场景

  1. 验证用户身份:

    • 在每个请求中解析 JWT,以确定请求是否来自合法用户。
  2. 提取用户信息:

    • 将用户信息注入HttpContext.User,供后续的中间件、控制器或服务访问。
  3. 统一用户上下文:

    • 所有基于身份的功能(如角色授权、权限验证)都依赖于HttpContext.User
  4. 轻量级认证:

    • 在无状态的 RESTful API 中,通过 JWT 中间件实现无会话的认证和上下文管理。

总结

通过自定义中间件解析 JWT,可以高效、灵活地处理用户上下文信息,将其注入到HttpContext.User 中,方便后续的业务逻辑开发。这种方式适用于 RESTful API、微服务架构等无状态的场景,增强了系统的安全性和可扩展性。

posted @   跟着阿笨一起玩.NET  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
历史上的今天:
2021-02-04 SQL Server数据库高级进阶之事务实战演练
2021-02-04 C#如何正确运用异步编程技术
2021-02-04 SQL Server数据库高级进阶之锁实战演练
2020-02-04 .NET Core基于SQL Server数据库主从同步实现读写分离实战演练
2013-02-04 将要被社会淘汰的8种人
点击右上角即可分享
微信分享提示