CSharp.Template/YuanXuan.IM.Common/Helpers/JwtHelper.cs

134 lines
4.9 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 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;
}
}
}