using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Security.Cryptography; using System.Text; namespace Health.Infrastructure.Services; /// /// JWT Token 生成与验证服务 /// public sealed class JwtProvider { private readonly string _secret; private readonly string _issuer; private readonly string _audience; public JwtProvider(IConfiguration configuration) { _secret = configuration["JWT_SECRET"] ?? "dev-secret-key-change-in-production-min-32-chars!!"; _issuer = configuration["JWT_ISSUER"] ?? "health-manager"; _audience = configuration["JWT_AUDIENCE"] ?? "health-manager-app"; } /// /// 生成 access_token(30 分钟有效) /// public string GenerateAccessToken(Guid userId, string phone) { var claims = new[] { new Claim(ClaimTypes.NameIdentifier, userId.ToString()), new Claim(ClaimTypes.MobilePhone, phone), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secret)); var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: _issuer, audience: _audience, claims: claims, expires: DateTime.UtcNow.AddMinutes(30), signingCredentials: credentials ); return new JwtSecurityTokenHandler().WriteToken(token); } /// /// 生成 refresh_token(30 天有效) /// public string GenerateRefreshToken() { var randomBytes = new byte[64]; using var rng = RandomNumberGenerator.Create(); rng.GetBytes(randomBytes); return Convert.ToBase64String(randomBytes); } /// /// 验证 JWT token 并返回 ClaimsPrincipal /// public TokenValidationParameters GetValidationParameters() { return new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = _issuer, ValidAudience = _audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secret)), ClockSkew = TimeSpan.Zero }; } }