.net core 3.1 Jwt操作封裝類,JwtHelper,支持生成、刷新等

最近在開發項目中,為了便於操作jwt,自己封裝了一個jwthelper,發出來,供大家一起討論。


.net core 3.1 Jwt操作封裝類,JwtHelper,支持生成、刷新等


<code>using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Text.RegularExpressions;
using TianFeng.FrameworkCore.Extensions;

namespace TFCMS.Tools
{

//iss: jwt簽發者
//sub: jwt所面向的用戶
//aud: 接收jwt的一方
//exp: jwt的過期時間,這個過期時間必須要大於簽發時間
//nbf: 定義在什麼時間之前,該jwt都是不可用的.
//iat: jwt的簽發時間
//jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。
//var jwt_id = User.Claims.FirstOrDefault(p => p.Type == "jti").Value;
//User.Claims.Select(p => new { p.Type, p.Value



/// <summary>
/// Jwt設置
/// /<summary>
public class JwtSettings
{

/// <summary>
/// 發行人
/// /<summary>
public string Issuer { get; set; }


/// <summary>
/// 訂閱者
/// /<summary>
public string Audience { get; set; }


/// <summary>
/// 加密key
/// /<summary>
public string SecurityKey { get; set; }


/// <summary>
/// 過期分鐘
/// /<summary>
public int ExpMinutes { get; set; }

}


/// <summary>
/// Jwt載荷信息
/// /<summary>
public class JwtPayload
{
public string UserId { get; set; }

public string UserName { get; set; }

public string RoleId { get; set; }

public DateTime ExpTime { get; set; }
}



/// <summary>
/// Jwt幫助類
/// /<summary>
public static class JwtHelper
{

private static JwtSettings settings;
public static JwtSettings Settings { set { settings = value; } get { return settings; } }

/// <summary>
/// 生成token
/// /<summary>

/// <param>
/// <returns>
public static string CreateToken(IEnumerable<claim> claims)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(settings.SecurityKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var securityToken = new JwtSecurityToken(
issuer: settings.Issuer,
audience: settings.Audience,
claims: claims,
//expires: DateTime.Now.AddMinutes(settings.ExpMinutes),
signingCredentials: creds);
var token = new JwtSecurityTokenHandler().WriteToken(securityToken);
return token;
}


/// <summary>
/// 生成Jwt
/// /<summary>
/// <param>
/// <param>
/// <param>
/// <returns>
public static string CreateToken(string userName, string roleId, string userId)
{
//聲明claim
var claims = new Claim[] {
new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.Jti, userId),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToUnixDate().ToString(), ClaimValueTypes.Integer64),//簽發時間
new Claim(JwtRegisteredClaimNames.Nbf, DateTime.UtcNow.ToUnixDate().ToString(), ClaimValueTypes.Integer64),//生效時間
new Claim(JwtRegisteredClaimNames.Exp, DateTime.Now.AddMinutes(settings.ExpMinutes).ToUnixDate().ToString(), ClaimValueTypes.Integer64), //過期時間
new Claim(JwtRegisteredClaimNames.Iss, settings.Issuer),
new Claim(JwtRegisteredClaimNames.Aud, settings.Audience),
new Claim(ClaimTypes.Name, userName),
new Claim(ClaimTypes.Role, roleId),
new Claim(ClaimTypes.Sid, userId)
};
return CreateToken(claims);
}


/// <summary>
/// 刷新token
/// /<summary>
/// <returns>
public static string RefreshToken(string oldToken)
{

var pl = GetPayload(oldToken);
//聲明claim
var claims = new Claim[] {
new Claim(JwtRegisteredClaimNames.Sub, pl?.UserName),
new Claim(JwtRegisteredClaimNames.Jti, pl?.UserId),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToUnixDate().ToString(), ClaimValueTypes.Integer64),//簽發時間
new Claim(JwtRegisteredClaimNames.Nbf, DateTime.UtcNow.ToUnixDate().ToString(), ClaimValueTypes.Integer64),//生效時間
new Claim(JwtRegisteredClaimNames.Exp, DateTime.Now.AddMinutes(settings.ExpMinutes).ToUnixDate().ToString(), ClaimValueTypes.Integer64), //過期時間
new Claim(JwtRegisteredClaimNames.Iss, settings.Issuer),
new Claim(JwtRegisteredClaimNames.Aud, settings.Audience),
new Claim(ClaimTypes.Name, pl?.UserName),
new Claim(ClaimTypes.Role, pl?.RoleId),
new Claim(ClaimTypes.Sid, pl?.UserId)
};

return IsExp(oldToken) ? CreateToken(claims) : null;
}


/// <summary>
/// 從token中獲取用戶身份
/// /<summary>
/// <param>
/// <returns>
public static IEnumerable<claim> GetClaims(string token)
{
var handler = new JwtSecurityTokenHandler();
var securityToken = handler.ReadJwtToken(token);
return securityToken?.Claims;
}


/// <summary>
/// 從Token中獲取用戶身份
/// /<summary>
/// <param>
/// <returns>
public static ClaimsPrincipal GetPrincipal(string token)
{
var handler = new JwtSecurityTokenHandler();
try
{
return handler.ValidateToken(token, new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = false,
ValidateIssuerSigningKey = true,

IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(settings.SecurityKey)),
ValidateLifetime = false
}, out SecurityToken validatedToken);
}
catch (Exception)
{
return null;
}
}


/// <summary>
/// 校驗Token
/// /<summary>
/// <param>token
/// <returns>
public static bool CheckToken(string token)
{
var principal = GetPrincipal(token);
if (principal is null)
{
return false;
}
return true;
}


/// <summary>
/// 獲取Token中的載荷數據
/// /<summary>
/// <param>token
/// <returns>
public static JwtPayload GetPayload(string token)
{
var jwtHandler = new JwtSecurityTokenHandler();
JwtSecurityToken securityToken = jwtHandler.ReadJwtToken(token);
return new JwtPayload
{
UserId = securityToken.Id,
UserName = securityToken.Payload[JwtRegisteredClaimNames.Sub]?.ToString(),
RoleId = (securityToken.Payload[ClaimTypes.Role] ?? 0).ToString(),
ExpTime = (securityToken.Payload[JwtRegisteredClaimNames.Exp] ?? 0).TimeStampToDate()
};
}


/// <summary>
/// 獲取Token中的載荷數據
/// /<summary>

/// <typeparam>泛型/<typeparam>
/// <param>token
/// <returns>
public static T GetPayload(string token)
{
var jwtHandler = new JwtSecurityTokenHandler();
JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(token);
return JsonConvert.DeserializeObject(jwtToken.Payload.SerializeToJson());
}


/// <summary>
/// 判斷token是否過期
/// /<summary>
/// <param>
/// <returns>
public static bool IsExp(string token)
{
return GetPrincipal(token)?.Claims.First(c => c.Type == JwtRegisteredClaimNames.Exp)?.Value?.TimeStampToDate() < DateTime.Now;
//return GetPayload(token).ExpTime < DateTime.Now;
}

#region 從上下文請求流操作

/// <summary>
/// 判斷是否為AJAX請求
/// /<summary>
/// <param>
/// <returns>
public static bool IsAjaxRequest(HttpRequest req)
{
bool result = false;

var xreq = req.Headers.ContainsKey("x-requested-with");
if (xreq)
{
result = req.Headers["x-requested-with"] == "XMLHttpRequest";
}

return result;
}


/// <summary>
/// 獲取Token
/// /<summary>

/// <param>請求流
/// <returns>
public static string GetToken(HttpRequest req)
{
string tokenHeader = req.Headers["Authorization"].ToString();
if (string.IsNullOrEmpty(tokenHeader))
throw new Exception("缺少token!");

string pattern = "^Bearer (.*?)$";
if (!Regex.IsMatch(tokenHeader, pattern))
throw new Exception("token格式不對!格式為:Bearer {token}");

string token = Regex.Match(tokenHeader, pattern).Groups[1]?.ToString();
if (string.IsNullOrEmpty(token))
throw new Exception("token不能為空!");

return token;
}

#endregion


}
}
/<claim>/<claim>/<code>


分享到:


相關文章: