共计 2227 个字符,预计需要花费 6 分钟才能阅读完成。
背景与痛点
在传统的 Web 应用中,Session 认证是最常见的用户认证方式。服务器保存用户状态,浏览器通过 Cookie 携带 Session ID。但这种模式存在几个明显问题:

- 服务器内存压力 :每个活跃用户都会占用服务器内存
- 横向扩展困难 :需要 Session 共享机制才能支持多服务器
- CSRF 风险 :依赖 Cookie 容易遭受跨站请求伪造攻击
JWT(JSON Web Token) 则采用无状态方案,所有认证信息都包含在 Token 本身中。它的优势包括:
- 自包含:Token 内直接存储用户声明 (Claims)
- 跨域友好:可通过 URL、Header 等多种方式传递
- 签名保护:防止内容被篡改
技术选型
常见的认证方案各有适用场景:
- Cookie/Session:适合传统 Web 应用,需要服务端状态维护
- OAuth2:适合第三方授权场景,如社交登录
- JWT:适合前后端分离架构,特别是移动端和 API 服务
对于大多数 C# Web API 项目,JWT 提供了最佳的平衡点:
- 实现简单,不需要额外存储
- 天然支持分布式系统
- 客户端处理逻辑统一
核心实现
1. 安装必要 NuGet 包
dotnet add package System.IdentityModel.Tokens.Jwt
2. 配置 JWT 服务
在 ASP.NET Core 的 Program.cs 中添加:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "your-issuer",
ValidateAudience = true,
ValidAudience = "your-audience",
ValidateLifetime = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-256-bit-secret")),
ValidateIssuerSigningKey = true,
};
});
3. 生成 Token 的示例代码
public string GenerateJwtToken(User user)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-256-bit-secret"));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.Role, user.Role)
};
var token = new JwtSecurityToken(
issuer: "your-issuer",
audience: "your-audience",
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
4. 登录接口实现
[HttpPost("login")]
public IActionResult Login([FromBody] LoginModel model)
{var user = _userService.Authenticate(model.Username, model.Password);
if (user == null)
return Unauthorized();
var token = GenerateJwtToken(user);
return Ok(new { Token = token});
}
安全考量
1. 防止 Token 被盗用
- 始终使用 HTTPS 传输
- 设置合理的过期时间 (建议 30 分钟 - 2 小时)
- 避免在 URL 中传递 Token
2. 敏感信息存储
- 不要在 Token 中存储密码等敏感信息
- 用户 ID 使用 GUID 而非自增整数
- 角色声明使用最小权限原则
3. 防范重放攻击
- 使用 JTI(令牌唯一标识) 确保一次性使用
- 服务端维护短期黑名单
生产环境建议
性能优化
- 对频繁验证的 Token 进行内存缓存
- 使用 RS256 算法将验证负载转移到客户端
- 批量验证多个 API 调用中的相同 Token
错误排查
常见问题包括:
- 签名不匹配:检查密钥是否一致
- 过期时间无效:确保服务器时间准确
- 声明缺失:验证 Claims 配置是否正确
监控建议
- 记录失败的认证尝试
- 监控 Token 生成频率
- 追踪异常长的 Token 有效期
思考题
在分布式系统中实现 Token 吊销的几种方案:
- 维护 Token 黑名单数据库
- 使用短期 Token 配合刷新 Token
- 基于事件的吊销通知机制
- 将吊销状态编码到 Token 本身 (如版本号)
每种方案都有其适用场景和性能考量,需要根据具体业务需求选择最合适的实现方式。
正文完
