微服务JWT认证授权:是否需Identity Server/OpenIddict?
不用Identity Server/OpenIddict,仅用ASP.NET 7 Identity实现微服务JWT认证授权
完全可以不用Identity Server或OpenIddict,仅靠ASP.NET 7 Identity就能实现你的需求。下面是具体的实现步骤:
1. 在认证服务中生成JWT令牌
首先需要一个负责处理登录的服务(可以是单独的Auth API,也可以是某个业务API里的登录端点),用ASP.NET Identity验证用户名密码,并生成JWT:
核心代码示例(登录控制器)
[ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly UserManager<IdentityUser> _userManager; private readonly IConfiguration _configuration; public AuthController(UserManager<IdentityUser> userManager, IConfiguration configuration) { _userManager = userManager; _configuration = configuration; } [HttpPost("login")] public async Task<IActionResult> Login([FromBody] LoginModel model) { // 用Identity验证用户名密码 var user = await _userManager.FindByNameAsync(model.Username); if (user != null && await _userManager.CheckPasswordAsync(user, model.Password)) { // 构建用户Claims var claims = new List<Claim> { new Claim(ClaimTypes.Name, user.UserName), new Claim(ClaimTypes.NameIdentifier, user.Id) }; // 添加角色Claims(如果用了角色) var roles = await _userManager.GetRolesAsync(user); claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role))); // 生成JWT令牌 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.AddHours(1), signingCredentials: creds); return Ok(new { Token = new JwtSecurityTokenHandler().WriteToken(token) }); } return Unauthorized(); } }
关键配置(appsettings.json)
所有微服务的配置里要包含相同的JWT参数:
"Jwt": { "Key": "你的强对称密钥(所有服务共享)", "Issuer": "你的认证服务域名", "Audience": "你的微服务受众标识" }
2. 在各个微服务中配置JWT认证
在服务A、B的Program.cs中添加JWT认证中间件,自动验证请求中的Bearer令牌:
核心代码示例
var builder = WebApplication.CreateBuilder(args); // 添加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"])) }; }); // 添加授权 builder.Services.AddAuthorization(); var app = builder.Build(); // 启用认证和授权中间件 app.UseAuthentication(); app.UseAuthorization(); // 其他中间件和路由配置...
这样配置后,所有带[Authorize]特性的控制器/Action会自动验证请求头中的Authorization: Bearer <token>令牌,验证通过才允许访问。
3. 基于Claims实现授权逻辑
你可以直接用角色或自定义Claims来控制访问:
示例1:基于角色授权
[Authorize(Roles = "Admin")] [ApiController] [Route("api/admin")] public class AdminController : ControllerBase { // 仅Admin角色可访问的接口 }
示例2:自定义Policy授权
先在Program.cs中定义Policy:
builder.Services.AddAuthorization(options => { options.AddPolicy("CanEditOrder", policy => policy.RequireClaim("Permission", "EditOrder")); });
然后在Action上使用:
[Authorize(Policy = "CanEditOrder")] [HttpPut("orders/{id}")] public IActionResult EditOrder(int id, [FromBody] OrderModel model) { // 仅持有"Permission:EditOrder" Claim的用户可访问 }
关键说明
- 令牌验证的核心:所有微服务必须共享同一个JWT签名密钥(或非对称密钥的公钥),这样才能确认令牌是由信任的认证服务签发的,没有被篡改。
- 为什么不用Identity Server/OpenIddict:这些框架是为复杂身份场景设计的(比如单点登录、OAuth2.0授权码流、客户端凭证流等),如果你的需求只是简单的用户名密码登录+JWT验证,ASP.NET Identity完全足够,不需要额外引入复杂框架。
内容的提问来源于stack exchange,提问作者Luka
相关产品推荐
相关产品推荐

