天天看点

JWT 帮助类 JWTHelper

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