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