Files
f9-web-ai-test/backend/F9WebAiTest.Application/Services/Auth/JwtService.cs
T
2026-10-08 10:43:59 +08:00

103 lines
3.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using F9WebAiTest.Domain.Entities.SYS.RBAC;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
namespace F9WebAiTest.Application.Services.Auth;
public class JwtService : IJwtService
{
private readonly IConfiguration _config;
public JwtService(IConfiguration config)
{
_config = config;
}
// 生成 access token(短期,如 2 小时)
public string GenerateAccessToken(User user, IEnumerable<string> roles)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new List<Claim>
{
new("id", user.Id.ToString()),
new(ClaimTypes.Name, user.LoginName),
new("realName", user.UserName)
};
foreach (var r in roles)
{
claims.Add(new Claim(ClaimTypes.Role, r));
}
var expireMinutes = int.Parse(_config["Jwt:AccessTokenExpireMinutes"] ?? "120");
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.UtcNow.AddMinutes(expireMinutes),
signingCredentials: creds
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
// 生成 refresh token(随机字符串,长期,如 7 天)
public string GenerateRefreshToken()
{
var randomNumber = new byte[64];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}
public (long id, string username) ValidateAccessToken(string token)
{
var handler = new JwtSecurityTokenHandler();
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var validationParams = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateIssuer = true,
ValidIssuer = _config["Jwt:Issuer"],
ValidateAudience = true,
ValidAudience = _config["Jwt:Audience"],
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
var principal = handler.ValidateToken(token, validationParams, out _);
var id = long.Parse(principal.FindFirst("id")!.Value);
var username = principal.Identity!.Name;
return (id, username);
}
// 校验 refresh token 的签名(refresh token 也是 JWT,但只含 id claim)
public long? ValidateRefreshToken(string token)
{
try
{
var handler = new JwtSecurityTokenHandler();
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var validationParams = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = false
};
var principal = handler.ValidateToken(token, validationParams, out _);
return long.Parse(principal.FindFirst("id")!.Value);
}
catch
{
return null;
}
}
}