C# JWT实现Token登录验证:从原理到生产环境实战

1次阅读
没有评论

共计 2722 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

背景痛点

在传统的单体应用架构中,Session 认证是常见的用户认证方式。但随着微服务架构的流行,Session 的局限性逐渐暴露:

C# JWT 实现 Token 登录验证:从原理到生产环境实战

  • 服务器内存开销大,每个用户会话都需要存储
  • 难以跨服务共享,需要依赖粘性会话或中央存储
  • 扩展性差,新增服务器节点时需要同步 Session
  • CSRF 防护依赖额外机制(如 Anti-Forgery Token)

技术选型

JWT 与 OAuth2/OIDC 都是现代认证方案,但适用场景不同:

  • JWT
  • 自包含令牌,适合服务间信任的简单场景
  • 无状态,服务端不需要存储会话信息
  • 轻量级,适合移动端和前后端分离架构

  • OAuth2/OIDC

  • 适合第三方授权场景(如使用 Google/Facebook 登录)
  • 需要授权服务器参与,流程更复杂
  • 支持更细粒度的权限控制

对于大多数内部系统,JWT 提供了足够的安全性和简便性。

核心实现

1. 安装必要 NuGet 包

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package System.IdentityModel.Tokens.Jwt

2. Startup 配置

// Program.cs
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };
    });

3. Token 生成服务

public class TokenService
{
    private readonly IConfiguration _configuration;

    public TokenService(IConfiguration configuration)
    {_configuration = configuration;}

    public string GenerateToken(User user)
    {var claims = new[]
        {new Claim(JwtRegisteredClaimNames.Sub, user.Id),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim(ClaimTypes.Name, user.Username),
            new Claim(ClaimTypes.Role, user.Role)
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var expires = DateTime.Now.AddMinutes(Convert.ToDouble(_configuration["Jwt:ExpireMinutes"]));

        var token = new JwtSecurityToken(issuer: _configuration["Jwt:Issuer"],
            audience: _configuration["Jwt:Audience"],
            claims: claims,
            expires: expires,
            signingCredentials: creds
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}

4. 登录控制器

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    private readonly TokenService _tokenService;

    public AuthController(TokenService tokenService)
    {_tokenService = tokenService;}

    [HttpPost("login")]
    public IActionResult Login([FromBody] LoginRequest request)
    {
        // 1. 验证用户凭证(省略具体实现)var user = AuthenticateUser(request.Username, request.Password);
        if (user == null)
            return Unauthorized();

        // 2. 生成 Token
        var token = _tokenService.GenerateToken(user);

        // 3. 返回 Token 和刷新 Token
        return Ok(new 
        {
            token,
            refreshToken = GenerateRefreshToken(user.Id)
        });
    }
}

安全考量

1. 密钥管理

  • 生产环境不要硬编码密钥
  • 使用密钥管理系统(如 Azure Key Vault)
  • 定期轮换密钥

2. Token 存储

方案 优点 缺点
客户端存储 无服务器开销 有 XSS 风险
HttpOnly Cookie 防 XSS 需处理 CSRF
Redis 集中存储 可主动失效 引入依赖

3. 敏感信息处理

  • 不要在 JWT 中存储密码等敏感信息
  • 必要时加密 Payload
  • 使用短期有效的 Token

避坑指南

  1. 时钟偏移问题
  2. 服务器间时间不同步会导致 Token 验证失败
  3. 设置 ClockSkew 容忍小范围偏差

  4. 性能优化

  5. 减少 Claims 数量
  6. 考虑使用引用 Token+ 数据库查询的方案

  7. 日志监控

  8. 记录异常的 Token 验证
  9. 监控 Token 生成频率

开放问题

在分布式系统中,如何实现 JWT 的主动失效?常见方案包括:

  • 维护 Token 黑名单
  • 使用短期 Token+ 长期 RefreshToken
  • 在网关层统一校验

每种方案各有什么优缺点?欢迎在评论区分享你的见解。

正文完
 0
评论(没有评论)