134 lines
4.9 KiB
C#
134 lines
4.9 KiB
C#
using Microsoft.IdentityModel.Tokens;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.IdentityModel.Tokens.Jwt;
|
||
using System.Linq;
|
||
using System.Security.Claims;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using YuanXuan.IM.Common.Configs;
|
||
using Microsoft.Extensions.Configuration;
|
||
using System.Reflection;
|
||
using System.IO;
|
||
|
||
namespace YuanXuan.IM.Common.Helpers
|
||
{
|
||
public class JwtHelper
|
||
{
|
||
private static JwtSettings _jwtSettings;
|
||
|
||
static JwtHelper()
|
||
{
|
||
// 初始化JWT配置
|
||
var configuration = new ConfigurationBuilder()
|
||
.SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
|
||
.AddJsonFile("appsettings.json", optional: true)
|
||
.AddJsonFile("appsettings.Development.json", optional: true)
|
||
.Build();
|
||
|
||
_jwtSettings = configuration.GetSection("Jwt").Get<JwtSettings>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成token
|
||
/// </summary>
|
||
/// <param name="uid"></param>
|
||
/// <param name="secretKey"></param>
|
||
/// <param name="issuer"></param>
|
||
/// <param name="audience"></param>
|
||
/// <param name="expires"></param>
|
||
/// <param name="claims"></param>
|
||
/// <returns></returns>
|
||
public static string CreateToken(string uid, string secretKey, string issuer, string audience, double expires, List<Claim> claims = null)
|
||
{
|
||
if (claims.IsNullOrEmpty())
|
||
claims = new();
|
||
claims.AddRange(new List<Claim>
|
||
{
|
||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
||
new Claim(ClaimTypes.NameIdentifier, uid),
|
||
});
|
||
|
||
// 2. 从 appsettings.json 中读取SecretKey
|
||
var secret = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
|
||
|
||
// 3. 选择加密算法
|
||
var algorithm = SecurityAlgorithms.HmacSha256;
|
||
|
||
// 4. 生成Credentials
|
||
var signingCredentials = new SigningCredentials(secret, algorithm);
|
||
|
||
// 5. 根据以上,生成token
|
||
var jwtSecurityToken = new JwtSecurityToken(
|
||
issuer, //Issuer
|
||
audience, //Audience
|
||
claims, //Claims,
|
||
DateTime.Now, //notBefore
|
||
DateTime.Now.AddSeconds(expires), //expires
|
||
signingCredentials //Credentials
|
||
);
|
||
|
||
// 6. 将token变为string
|
||
var token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
|
||
|
||
return token;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成JWT token
|
||
/// </summary>
|
||
/// <param name="userId"></param>
|
||
/// <param name="userName"></param>
|
||
/// <returns></returns>
|
||
public static string GenerateToken(string userId, string userName)
|
||
{
|
||
var claims = new List<Claim>
|
||
{
|
||
new Claim(JwtRegisteredClaimNames.Sub, userId),
|
||
new Claim(JwtRegisteredClaimNames.Name, userName),
|
||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
||
};
|
||
|
||
return CreateToken(userId, _jwtSettings.AccessSecret, _jwtSettings.Issuer, _jwtSettings.Audience, _jwtSettings.AccessExpiration);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成刷新token
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public static string GenerateRefreshToken()
|
||
{
|
||
return Guid.NewGuid().ToString("N");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从过期的token中获取principal
|
||
/// </summary>
|
||
/// <param name="token"></param>
|
||
/// <returns></returns>
|
||
public static ClaimsPrincipal GetPrincipalFromExpiredToken(string token)
|
||
{
|
||
var tokenValidationParameters = new TokenValidationParameters
|
||
{
|
||
ValidateIssuer = true,
|
||
ValidIssuer = _jwtSettings.Issuer,
|
||
ValidateAudience = true,
|
||
ValidAudience = _jwtSettings.Audience,
|
||
ValidateIssuerSigningKey = true,
|
||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.AccessSecret)),
|
||
ValidateLifetime = false // 不验证过期时间
|
||
};
|
||
|
||
var tokenHandler = new JwtSecurityTokenHandler();
|
||
var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out var securityToken);
|
||
|
||
if (!(securityToken is JwtSecurityToken jwtSecurityToken) || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
|
||
{
|
||
throw new SecurityTokenException("无效的token");
|
||
}
|
||
|
||
return principal;
|
||
}
|
||
}
|
||
}
|