阿杰,我给你详细讲一下 ASP.NET Core Web API 中 Token 验证 的实现,从原理到代码一步步来,让你能直接在项目中落地。
1. Token 验证的基本思路
在 Web API 中,Token 验证通常指 客户端拿到一个令牌(Token)后,每次请求都在 HTTP Header 中携带它,服务端验证 Token 是否有效。
常见 Token 类型:
- JWT (JSON Web Token) ✅ 主流,跨平台支持好
- 自定义加密 Token(适合简单场景)
- OAuth2 Access Token(更复杂的授权系统)
这里我用 JWT 举例,因为它是 ASP.NET Core 的标准做法。
2. JWT 验证流程
- 用户登录 → 服务器验证账号密码 → 生成 JWT → 返回给客户端
- 客户端发起请求 → 在
Authorization
请求头里带上:Authorization: Bearer <token>
- 服务器验证 JWT → 如果有效,解析出用户信息 → 允许访问
3. 安装 NuGet 包
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package System.IdentityModel.Tokens.Jwt
4. 生成 JWT Token
在 Services
中写一个 JwtHelper
:
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.Text;
public class JwtHelper
{
private readonly string _key = "your_secret_key_here"; // 存到配置文件更安全
private readonly string _issuer = "yourapp";
private readonly string _audience = "yourapp_users";
public string GenerateToken(string username, string role, int expireMinutes = 60)
{
var claims = new[]
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.Role, role)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_key));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _issuer,
audience: _audience,
claims: claims,
expires: DateTime.UtcNow.AddMinutes(expireMinutes),
signingCredentials: creds
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
5. 配置 JWT 验证
Program.cs
:
var builder = WebApplication.CreateBuilder(args);
var key = "your_secret_key_here"; // 应该从配置文件读取
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "yourapp",
ValidateAudience = true,
ValidAudience = "yourapp_users",
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)),
ClockSkew = TimeSpan.Zero // 去掉默认的5分钟缓冲
};
});
builder.Services.AddAuthorization();
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication(); // 必须放在 UseAuthorization 之前
app.UseAuthorization();
app.MapControllers();
app.Run();
6. 登录接口(颁发 Token)
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly JwtHelper _jwt;
public AuthController(JwtHelper jwt)
{
_jwt = jwt;
}
[HttpPost("login")]
public IActionResult Login([FromBody] LoginRequest request)
{
// 假设这里验证用户名密码
if (request.Username == "admin" && request.Password == "123456")
{
var token = _jwt.GenerateToken(request.Username, "Admin");
return Ok(new { token });
}
return Unauthorized("用户名或密码错误");
}
}
public class LoginRequest
{
public string Username { get; set; }
public string Password { get; set; }
}
7. 受保护的 API
[ApiController]
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
[HttpGet]
[Authorize] // 需要携带有效 Token 才能访问
public IActionResult Get()
{
var username = User.Identity.Name;
var role = User.FindFirst(ClaimTypes.Role)?.Value;
return Ok(new { message = $"欢迎 {username},角色:{role}" });
}
}
8. 客户端请求示例
- 登录获取 Token
POST /api/auth/login
{
"username": "admin",
"password": "123456"
}
返回:
{
"token": "eyJhbGciOiJIUzI1NiIs..."
}
- 携带 Token 访问受保护 API
GET /api/values
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
9. 最佳实践
- 密钥管理:密钥存到配置文件(
appsettings.json
)或环境变量,不要写死代码。 - Token 过期刷新:可以加 Refresh Token 机制。
- 角色/权限控制:配合
[Authorize(Roles="Admin")]
做细粒度控制。 - HTTPS:生产环境必须用 HTTPS,防止 Token 被窃取。
- 前端存储 Token:推荐存到
localStorage
或sessionStorage
,不要放 Cookie(除非做 HttpOnly)。
发表回复