ASP.NET Core多服务共享JWT Token授权问题咨询
当然可以!JwtBearer认证方案正是为这类跨API授权场景设计的——它能让API B可靠验证API A签发的JWT令牌,实现安全的跨服务访问控制。下面我一步步给你讲具体怎么配置:
一、API A(令牌签发方)的配置
API A的核心是生成符合规范的JWT令牌,需要先配置JWT的基础参数,再实现登录接口生成令牌。
- 配置JWT服务
在Program.cs中添加认证服务,并配置JWT的验证参数(这些参数会被用来生成合法的令牌):
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; 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, // 这些参数要和API B保持完全一致 ValidIssuer = builder.Configuration["Jwt:Issuer"], // 示例:"https://apia.example.com" ValidAudience = builder.Configuration["Jwt:Audience"], // 示例:"https://apib.example.com" IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) // 加密密钥,建议用复杂字符串 }; }); // 添加控制器服务 builder.Services.AddControllers(); var app = builder.Build(); // 启用认证中间件 app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
- 实现登录接口生成令牌
创建一个登录接口,验证用户账号密码后生成JWT返回给客户端:
using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; [ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly IConfiguration _configuration; private readonly IUserService _userService; // 假设你有自定义的用户验证服务 public AuthController(IConfiguration configuration, IUserService userService) { _configuration = configuration; _userService = userService; } [HttpPost("login")] public IActionResult Login([FromBody] LoginRequest request) { // 第一步:验证用户账号密码合法性 var validUser = _userService.ValidateCredentials(request.Username, request.Password); if (validUser == null) { return Unauthorized("账号或密码错误"); } // 第二步:构造JWT的Claims(自定义用户信息,比如用户名、角色) var claims = new List<Claim> { new Claim(JwtRegisteredClaimNames.Sub, validUser.Username), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(ClaimTypes.Role, validUser.Role) // 示例:添加角色权限Claim }; // 第三步:生成JWT令牌 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"])); var signingCreds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: _configuration["Jwt:Issuer"], audience: _configuration["Jwt:Audience"], claims: claims, expires: DateTime.UtcNow.AddMinutes(30), // 设置令牌过期时间 signingCredentials: signingCreds); // 返回令牌给客户端 return Ok(new { AccessToken = new JwtSecurityTokenHandler().WriteToken(token), ExpiresAt = token.ValidTo }); } } // 登录请求模型 public class LoginRequest { public string Username { get; set; } public string Password { get; set; } }
二、API B(资源服务方)的配置
API B需要配置JwtBearer来验证API A签发的令牌,核心是和API A使用完全一致的JWT参数。
- 配置JWT认证与授权
在Program.cs中添加认证和授权服务:
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; var builder = WebApplication.CreateBuilder(args); // 添加JWT认证服务,参数必须和API A完全匹配! builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], // 和API A一致 ValidAudience = builder.Configuration["Jwt:Audience"], // 和API A一致 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) // 和API A一致 }; }); // 添加授权服务 builder.Services.AddAuthorization(); // 添加控制器服务 builder.Services.AddControllers(); var app = builder.Build(); // 中间件顺序很重要:先认证,再授权 app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
- 保护API资源
在需要授权访问的控制器或Action上添加[Authorize]属性:
[ApiController] [Route("api/data")] [Authorize] // 添加该属性后,只有携带有效JWT的请求才能访问 public class DataController : ControllerBase { private readonly IDatabaseService _dbService; public DataController(IDatabaseService dbService) { _dbService = dbService; } [HttpGet] public IActionResult GetSensitiveData() { var data = _dbService.GetFromDatabase(); return Ok(data); } }
三、关键注意事项
- 核心配置必须一致:API A和API B的
ValidIssuer、ValidAudience、IssuerSigningKey必须完全相同,否则API B会拒绝验证令牌。 - 密钥安全:生产环境中不要硬编码密钥,建议使用环境变量、密钥管理工具存储,避免密钥泄露。
- 跨域问题:如果前端从API A获取令牌后调用API B,要确保API B配置了CORS,允许前端域名的跨域请求。
- 自定义验证:如果需要更复杂的授权逻辑(比如基于自定义Claim的验证),可以在
TokenValidationParameters中添加自定义验证逻辑,或者使用策略授权。
内容的提问来源于stack exchange,提问作者fosfuan
相关产品推荐
相关产品推荐

