如何在C# Web API的[Authorize]请求中获取JWT Token(Bearer Token)
在MySQL环境下实现JWT令牌的角色验证方案
一、完善JWT令牌生成逻辑,存入角色Claim
你的代码里已经关联了Cargo(角色),只需要在TokenService.GenerateToken方法中把角色信息加入JWT的Claim集合即可:
public static string GenerateToken(Usuario usuario) { var tokenHandler = new JwtSecurityTokenHandler(); // 从配置文件读取JWT密钥(建议存在appsettings.json中) var secretKey = Encoding.ASCII.GetBytes(Configuration["Jwt:SecretKey"]); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new List<Claim> { new Claim(ClaimTypes.NameIdentifier, usuario.Id.ToString()), new Claim(ClaimTypes.Name, $"{usuario.Nome} {usuario.Sobrenome}"), // 将角色名称存入Role类型的Claim new Claim(ClaimTypes.Role, usuario.Cargo.Nome) }), // 设置令牌过期时间,比如2小时 Expires = DateTime.UtcNow.AddHours(2), // 使用HMAC-SHA256算法签名令牌 SigningCredentials = new SigningCredentials( new SymmetricSecurityKey(secretKey), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); }
二、配置JWT认证中间件
在Program.cs中添加JWT认证和授权服务,确保请求到达接口前先验证令牌有效性:
var builder = WebApplication.CreateBuilder(args); // 添加JWT认证服务 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { // 验证签名密钥 ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey( Encoding.ASCII.GetBytes(builder.Configuration["Jwt:SecretKey"])), // 根据你的业务需求决定是否验证发行方和受众 ValidateIssuer = false, ValidateAudience = false }; }); // 添加授权服务 builder.Services.AddAuthorization(); // 注册MySQL DbContext builder.Services.AddDbContext<DataBaseContext>(options => options.UseMySql(builder.Configuration.GetConnectionString("DefaultConnection"), ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("DefaultConnection")))); var app = builder.Build(); // 中间件顺序必须正确:先认证,再授权 app.UseAuthentication(); app.UseAuthorization(); // 映射路由等其他配置 app.MapControllers(); app.Run();
三、修复原认证方法的异步调用问题
原代码中使用.Result调用异步查询容易引发死锁,改成await:
[HttpPost] [Route("")] public async Task<IActionResult> Auth([FromBody] AuthRequestModel authRequest) { var checkUsuario = await _dataBaseContext.Usuario .Include(u => u.Cargo) .FirstOrDefaultAsync(c => c.Email == authRequest.Usuario); if (checkUsuario == null) return NotFound("usuario nao encontrado"); var hash = new Hash(SHA256.Create()); var senhaCorreta = hash.VerificarSenha(authRequest.Senha, checkUsuario.Senha); if (!senhaCorreta) return BadRequest("Senha incorreta"); var userData = new { checkUsuario.Nome, checkUsuario.Sobrenome, checkUsuario.Id }; var token = TokenService.GenerateToken(checkUsuario); var response = new {userData, Token = token}; return Ok(response); }
四、验证角色的两种方式
1. 使用特性自动验证
在需要限制角色访问的接口上添加[Authorize(Roles = "你的角色名称")],中间件会自动验证令牌中的角色Claim:
[HttpGet("admin-dashboard")] [Authorize(Roles = "Admin")] public IActionResult AdminDashboard() { return Ok("只有管理员能访问此页面"); }
2. 手动解码令牌获取角色
如果需要在方法内手动获取或验证角色,可以通过HttpContext.User直接读取Claim:
[HttpGet("user-info")] [Authorize] // 先验证令牌有效性 public IActionResult GetUserInfo() { // 获取当前用户的ID和角色 var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var userRole = User.FindFirstValue(ClaimTypes.Role); // 自定义角色验证逻辑 if (userRole != "Editor" && userRole != "Admin") { return Forbid("无操作权限"); } return Ok(new { UserId = userId, Role = userRole }); }
内容的提问来源于stack exchange,提问作者Guilherme Vianna
相关产品推荐
相关产品推荐

