JWTPlayloadInfo.cs 代碼如下:
/// <summary>
/// JWT載荷實體
/// </summary>
public sealed class JWTPlayloadInfo
{
/// <summary>
/// jwt簽發者
/// </summary>
public string iss { get; set; } = "Berry.Service";
/// <summary>
/// jwt所面向的使用者 UserId
/// </summary>
public string sub { get; set; } = "";
/// <summary>
/// 接收jwt的一方
/// </summary>
public string aud { get; set; } = "";
/// <summary>
/// jwt的簽發時間
/// </summary>
public string iat { get; set; } = Utils.FormatDate(DateTime.Now, "1");
/// <summary>
/// jwt的過期時間,這個過期時間必須要大于簽發時間.預設60分鐘
/// </summary>
public string exp { get; set; }
public TimeSpan daySpan { get; set; }
/// <summary>
/// 定義在什麼時間之前,該jwt都是不可用的.
/// </summary>
public int nbf { get; set; }
public string ip { get; set; }
/// <summary>
/// jwt的唯一身份辨別,主要用來作為一次性token,進而回避重播攻擊。
/// </summary>
public string jti { get; set; } = Utils.GetGUID().ToString();
/// <summary>
/// 使用者ID。自定義字段
/// </summary>
public string userid { get; set; }
/// <summary>
/// 擴充字段。自定義字段
/// </summary>
public string extend { get; set; }
/// <summary>
/// 自定義對象
/// </summary>
public object data { get; set; }
public string token { get; set; }
}
JWTHelper.cs 代碼如下:
using Currency.Redis;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Currency.Common
{
/// <summary>
/// JWT操作幫助類
/// </summary>
public sealed class JWTHelper
{
/// <summary>
/// 簽發Token
/// </summary>
/// <param name="playload">載荷</param>
/// <returns></returns>
public static string GetToken(JWTPlayloadInfo playload)
{
string token = String.Empty;
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
IJsonSerializer serializer = new JsonNetSerializer();
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
//設定過期時間
DateTime time = DateTime.Now.Add(playload.daySpan);
if (!string.IsNullOrEmpty(playload.iat))
{
var iat = DateTime.Now;
try
{
iat = DateTime.Parse(playload.iat);
}
catch (Exception)
{
iat = DateTime.Now;
}
time = iat.Add(playload.daySpan);
}
playload.exp = Utils.GetTimeStamp(time);
//擷取私鑰
string secret = GetSecret();
if (!string.IsNullOrEmpty(playload.sub))
{
token = encoder.Encode(playload, secret);
}
return token;
}
/// <summary>
/// Token校驗
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public static JWTPlayloadInfo CheckToken(string token)
{
try
{
if (string.IsNullOrEmpty(token)) return null;
IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);
//擷取私鑰
string secret = GetSecret();
JWTPlayloadInfo playloadInfo = decoder.DecodeToObject<JWTPlayloadInfo>(token, secret, true);
if (playloadInfo != null)
{
if (!string.IsNullOrEmpty(playloadInfo.sub))
{
var cacheToken = RedisHelper.StringGet($"user:login:{playloadInfo.sub}:{playloadInfo.jti}");
return Check(playloadInfo, cacheToken, token) ? playloadInfo : null;
}
}
}
catch (Exception)
{
return null;
}
return null;
}
private static bool Check(JWTPlayloadInfo info, string cacheToken, string token)
{
if (string.IsNullOrEmpty(cacheToken)) return false;
if (string.IsNullOrEmpty(token)) return false;
if (!cacheToken.Equals(token)) return false;
//Token過期
DateTime exp = Utils.GetTime(info.exp);
if (DateTime.Now > exp)
{
if (!string.IsNullOrEmpty(info.sub))
{
RedisHelper.KeyDelete($"user:login:{info.sub}:{info.jti}");
}
return false;
}
return true;
}
/// <summary>
/// 擷取私鑰
/// </summary>
/// <returns></returns>
private static string GetSecret()
{
//TODO 從檔案中去讀真正的私鑰
return "eyJpc3MiOiJCZXJyeS5TZXJ2aWNlIiwic3ViIjoiMTgyODQ1OTQ2MTkiLCJhdWQiOiJndWVzdCIsImlhdCI6IjE1MzEzODE5OTgiLCJleHAiOiIxNTMxMzg5MTk4IiwibmJmIjowLCJqdGkiOiI1YzdmN2ZhM2E4ODVlODExYTEzNTQ4ZDIyNGMwMWQwNSIsInVzZXJpZCI6bnVsbCwiZXh0ZW5kIjpudWxsfQ";
}
}
}
其中用到了 RedisHelper,請參考另一篇文章 https://blog.csdn.net/u013608482/article/details/88397789