共计 3148 个字符,预计需要花费 8 分钟才能阅读完成。
背景与痛点
在现代 Web 开发中,身份验证是保障系统安全的重要环节。传统的 Session 验证方式虽然简单,但在分布式系统和微服务架构中暴露出明显不足:

- 服务器需要存储 Session 状态,增加了内存压力
- 跨域访问困难,不利于前后端分离架构
- 难以扩展,无法适应多服务器部署
- 移动端支持不佳
JWT(JSON Web Token)作为一种无状态验证方案,完美解决了这些问题。它通过加密的 JSON 对象在客户端和服务器之间安全传递信息,无需服务器保存验证状态。
JWT 核心概念
JWT 由三部分组成,通过点 (.) 连接:
- Header:包含令牌类型和使用的哈希算法
- Payload:包含声明(claims),即用户信息和附加数据
- Signature:对前两部分的签名,防止数据篡改
一个典型的 JWT 看起来像这样:
xxxxx.yyyyy.zzzzz
实现步骤
1. 配置 JWT 服务
首先在 Program.cs 中添加 JWT 服务配置:
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"]))
};
});
2. Token 生成与验证
创建 Token 生成服务:
public class TokenService
{
private readonly IConfiguration _configuration;
public TokenService(IConfiguration configuration)
{_configuration = configuration;}
public string GenerateToken(User user)
{var claims = new[]
{new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Username),
new Claim(ClaimTypes.Email, user.Email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(issuer: _configuration["Jwt:Issuer"],
audience: _configuration["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddMinutes(30), // 30 分钟有效期
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
3. Token 刷新机制
实现 Refresh Token 可以有效减少用户频繁登录:
public class AuthController : ControllerBase
{
// 登录接口
[HttpPost("login")]
public IActionResult Login([FromBody] LoginModel model)
{
// 验证用户逻辑...
var token = _tokenService.GenerateToken(user);
var refreshToken = _tokenService.GenerateRefreshToken();
// 保存 refreshToken 到数据库或缓存
_userService.SaveRefreshToken(user.Id, refreshToken);
return Ok(new
{
Token = token,
RefreshToken = refreshToken,
ExpiresIn = 1800 // 30 分钟
});
}
// 刷新 Token 接口
[HttpPost("refresh")]
public IActionResult Refresh([FromBody] RefreshModel model)
{
// 验证 refreshToken...
// 生成新 Token
var newToken = _tokenService.GenerateToken(user);
var newRefreshToken = _tokenService.GenerateRefreshToken();
// 更新数据库中的 refreshToken
_userService.UpdateRefreshToken(model.RefreshToken, newRefreshToken);
return Ok(new
{
Token = newToken,
RefreshToken = newRefreshToken,
ExpiresIn = 1800
});
}
}
安全考量
防止 Token 被盗用
- 始终使用 HTTPS 传输 Token
- 设置合理的 Token 过期时间(通常 15-30 分钟)
- 使用 HttpOnly 的 Cookie 存储 Token(Web 环境)
- 实现 Token 撤销机制
Token 过期策略
- Access Token: 短期有效(15-30 分钟)
- Refresh Token: 长期有效(7-30 天)
- 滑动过期: 用户活跃时延长会话
敏感信息处理
- 不要在 Payload 中存储敏感信息
- 必要时加密 Payload
- 使用强密钥(建议至少 256 位)
性能优化
- 使用高效的签名算法(HmacSha256)
- 避免在 Token 中存储过多 claims
- 考虑使用 Redis 缓存已验证的 Token
- 分布式环境下使用统一的密钥
生产环境避坑指南
- 密钥管理不当
- 错误:硬编码密钥或使用弱密钥
-
解决:从安全配置源获取,定期轮换
-
Token 泄露风险
- 错误:通过 URL 参数传递 Token
-
解决:使用 Authorization 头或 HttpOnly Cookie
-
过期时间过长
- 错误:设置数小时甚至数天的 Access Token
-
解决:短期 Token 配合 Refresh Token 机制
-
缺乏 Token 撤销
- 错误:无法在用户登出时使 Token 失效
-
解决:实现 Token 黑名单或短期 Token
-
跨域问题
- 错误:未配置 CORS 导致验证失败
- 解决:正确配置 CORS 策略
总结与扩展
本文介绍了 ASP.NET Core 中 JWT 验证的完整实现。在实际项目中,你可能还需要:
- 与 Identity Server 集成实现 OAuth2.0
- 添加多因素认证
- 实现基于策略的权限控制
思考题:在微服务架构中,如何实现跨服务的 Token 验证?
(提示:可以考虑使用 API 网关统一验证,或实现 Token 中继 / 转换)
正文完
