JWT(JSON Web Tokens)操作帮助类

载荷实体:

/// <summary>
    /// JWT载荷实体
    /// </summary>
    public sealed class JWTPlayloadInfo
    {
        /// <summary>
        /// jwt签发者
        /// </summary>
        public string iss { get; set; } = "Berry.Service";
        /// <summary>
        /// jwt所面向的用户
        /// </summary>
        public string sub { get; set; } = "ALL";
        /// <summary>
        /// 接收jwt的一方
        /// </summary>
        public string aud { get; set; } = "guest";
        /// <summary>
        /// jwt的签发时间
        /// </summary>
        public string iat { get; set; } = DateTimeHelper.GetTimeStamp(DateTime.Now).ToString();
        /// <summary>
        /// jwt的过期时间,这个过期时间必须要大于签发时间.默认60分钟
        /// </summary>
        public string exp { get; set; }
        /// <summary>
        /// 定义在什么时间之前,该jwt都是不可用的.
        /// </summary>
        public int nbf { get; set; }
        /// <summary>
        /// jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
        /// </summary>
        public string jti { get; set; } = CommonHelper.GetGuid();
        /// <summary>
        /// 用户ID。自定义字段
        /// </summary>
        public string userid { get; set; }
        /// <summary>
        /// 扩展字段。自定义字段
        /// </summary>
        public string extend { get; set; }
    }

JWTHelper.cs:

/// <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.AddMinutes(120);
            playload.exp = DateTimeHelper.GetTimeStamp(time).ToString();
            Dictionary<string, object> dict = playload.Object2Dictionary();
            //获取私钥
            string secret = GetSecret();
            //将Token保存在缓存中
            if (!string.IsNullOrEmpty(playload.aud) && playload.aud.Equals("guest"))
            {
                //计算公用Token
                token = CacheFactory.GetCacheInstance().GetCache("JWT_TokenCacheKey:Guest", () =>
                {
                    return encoder.Encode(dict, secret);
                }, time);
            }
            else
            {
                //计算Token
                token = CacheFactory.GetCacheInstance().GetCache($"JWT_TokenCacheKey:{playload.aud}", () =>
                {
                    return encoder.Encode(dict, secret);
                }, time);
            }
            return token;
        }

        /// <summary>
        /// Token校验
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static JWTPlayloadInfo CheckToken(string token)
        {
            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.aud) && playloadInfo.aud.Equals("guest"))
                {
                    string cacheToken = CacheFactory.GetCacheInstance().GetCache<string>("JWT_TokenCacheKey:Guest");

                    return Check(playloadInfo, cacheToken, token) ? playloadInfo : null;
                }
                else
                {
                    string cacheToken = CacheFactory.GetCacheInstance().GetCache<string>($"JWT_TokenCacheKey:{playloadInfo.aud}");
                    return Check(playloadInfo, cacheToken, token) ? playloadInfo : 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 = DateTimeHelper.GetDateTime(info.exp);
            if (DateTime.Now > exp)
            {
                if (!string.IsNullOrEmpty(info.aud) && info.aud.Equals("guest"))
                {
                    CacheFactory.GetCacheInstance().RemoveCache("JWT_TokenCacheKey:Guest");
                }
                else
                {
                    CacheFactory.GetCacheInstance().RemoveCache($"JWT_TokenCacheKey:{info.aud}");
                }
                return false;
            }
            return true;
        }

        /// <summary>
        /// 获取私钥
        /// </summary>
        /// <returns></returns>
        private static string GetSecret()
        {
            //TODO 从文件中去读真正的私钥
            return "eyJpc3MiOiJCZXJyeS5TZXJ2aWNlIiwic3ViIjoiMTgyODQ1OTQ2MTkiLCJhdWQiOiJndWVzdCIsImlhdCI6IjE1MzEzODE5OTgiLCJleHAiOiIxNTMxMzg5MTk4IiwibmJmIjowLCJqdGkiOiI1YzdmN2ZhM2E4ODVlODExYTEzNTQ4ZDIyNGMwMWQwNSIsInVzZXJpZCI6bnVsbCwiZXh0ZW5kIjpudWxsfQ";
        }
    }

自定义忽略验证特性:

/// <summary>
    /// 忽略验证
    /// </summary>
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
    public class IgnoreTokenAttribute : Attribute
    {
        public bool Ignore { get; set; }
        /// <summary>
        /// 忽略验证.默认忽略
        /// </summary>
        /// <param name="ignore"></param>
        public IgnoreTokenAttribute(bool ignore = true)
        {
            this.Ignore = ignore;
        }
    }

自定义Action拦截器,处理验证逻辑:

public class CustomActionFilterAttribute : ActionFilterAttribute
    {
        /// <summary>在调用操作方法之前发生。</summary>
        /// <param name="actionContext">操作上下文。</param>
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            string isInterfaceSignature = ConfigHelper.GetValue("IsInterfaceSignature");
            if (isInterfaceSignature.ToLower() == "false") return;

            BaseJsonResult<string> resultMsg = null;
            //授权码
            string accessToken = string.Empty;
            //操作上下文请求信息
            HttpRequestMessage request = actionContext.Request;
            //数字签名数据
            if (request.Headers.Contains("Authorization"))
            {
                accessToken = HttpUtility.UrlDecode(request.Headers.GetValues("Authorization").FirstOrDefault());
            }

            //接受客户端预请求
            if (actionContext.Request.Method == HttpMethod.Options)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Accepted);
                return;
            }

            //忽略不需要授权的方法
            var attributes = actionContext.ActionDescriptor.GetCustomAttributes<IgnoreTokenAttribute>();
            if (attributes.Count > 0 && attributes[0].Ignore) return;

            //判断请求头是否包含以下参数
            if (string.IsNullOrEmpty(accessToken))
            {
                resultMsg = new BaseJsonResult<string>
                {
                    Status = (int)JsonObjectStatus.ParameterError,
                    Message = JsonObjectStatus.ParameterError.GetEnumDescription()
                };
                actionContext.Response = resultMsg.ToHttpResponseMessage();
                return;
            }

            //校验Token是否有效
            JWTPlayloadInfo playload = JWTHelper.CheckToken(accessToken);
            if (playload == null)
            {
                resultMsg = new BaseJsonResult<string>
                {
                    Status = (int)JsonObjectStatus.TokenInvalid,
                    Message = JsonObjectStatus.TokenInvalid.GetEnumDescription()
                };
                actionContext.Response = resultMsg.ToHttpResponseMessage();
                return;
            }
            else
            {
                //校验当前用户是否能够操作某些特定方法(比如更新用户信息)
                if (!attributes[0].Ignore)
                {
                    if (!string.IsNullOrEmpty(playload.aud) && playload.aud.Equals("guest"))
                    {
                        resultMsg = new BaseJsonResult<string>
                        {
                            Status = (int)JsonObjectStatus.Unauthorized,
                            Message = JsonObjectStatus.Unauthorized.GetEnumDescription()
                        };
                        actionContext.Response = resultMsg.ToHttpResponseMessage();
                        return;
                    }
                }
            }

            base.OnActionExecuting(actionContext);
        }
    }

在WebApiConfig.cs中注册:

config.Filters.Add(new CustomActionFilterAttribute());

新增获取Token控制器,添加获取Token方法:

/// <summary>
        /// 获取授权Token
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        [HttpPost]
        [IgnoreToken(true)]
        public HttpResponseMessage GetJWTToken(GetTokenArgEntity arg)
        {
            BaseJsonResult<string> resultMsg = this.GetBaseJsonResult<string>();

            Logger(this.GetType(), "获取授权Token-GetJWTToken", () =>
            {
                if (!string.IsNullOrEmpty(arg.t))
                {
                    //TODO 根据UserID校验用户是否存在
                    if (true)
                    {
                        JWTPlayloadInfo playload = new JWTPlayloadInfo
                        {
                            iss = "Berry.Service",
                            sub = arg.Account,
                            aud = arg.UserId
                        };
                        string token = JWTHelper.GetToken(playload);

                        resultMsg = this.GetBaseJsonResult<string>(token, JsonObjectStatus.Success);
                    }
                    else
                    {
                        resultMsg = this.GetBaseJsonResult<string>("", JsonObjectStatus.UserNotExist);
                    }
                }
                else
                {
                    resultMsg = this.GetBaseJsonResult<string>("", JsonObjectStatus.Fail, ",请求参数有误。");
                }
            }, e =>
            {
                resultMsg = this.GetBaseJsonResult<string>("", JsonObjectStatus.Exception, ",异常信息:" + e.Message);
            });

            return resultMsg.ToHttpResponseMessage();
        }

获取Token参数实体:

/// <summary>
    /// 获取Token参数
    /// </summary>
    public class GetTokenArgEntity : BaseParameterEntity
    {
        /// <summary>
        /// 用户ID
        /// </summary>
        [Required(ErrorMessage = "UserId不能为空")]
        public string UserId { get; set; }
        /// <summary>
        /// 帐号
        /// </summary>
        [Required(ErrorMessage = "Account不能为空")]
        public string Account { get; set; }
    }

原文地址:https://www.cnblogs.com/zhao-yi/p/9317835.html

时间: 2024-08-28 02:28:56

JWT(JSON Web Tokens)操作帮助类的相关文章

JWT(JSON Web Tokens)

1.JWT即JSON Web Tokens,他可以用来安全的传递信息,因为这些信息是经过数字签名的 2.JWT可以使用一种加密算法比如HMAC 算法,也可以使用公钥/私钥的非对称算法 3.因为JWT签名后的信息够短,可以放在url里.request body里.http header里,传输够快. 4.荷载信息里包含所有你想要的,避免不止一次的去查询数据库 5.JWT的使用场景主要包括: 1) 认证,这是比较常见的使用场景,只要用户登录过一次系统,之后的请求都会包含签名出来的token,通过to

JSON Web Tokens(JWT)

现在API越来越流行,如何安全保护这些API? JSON Web Tokens(JWT)能提供基于JSON格式的安全认证.它有以下特点: JWT是跨不同语言的,JWT可以在 .NET, Python, Node.js, Java, PHP, Ruby, Go, JavaScript和Haskell中使用 JWT是自我包涵的,它们包含了必要的所有信息,这就意味着JWT能够传递关于它自己的基本信息,比如用户信息和签名等. JWT传递是容易的,因为JWT是自我包涵,它们能被完美用在HTTP头部中,当需

Go实战--golang中使用JWT(JSON Web Token)

http://blog.csdn.net/wangshubo1989/article/details/74529333 之前写过关于golang中如何使用cookie的博客: 实战–go中使用cookie 今天就来跟大家简单介绍一下golang中如何使用token,当然是要依赖一下github上的优秀的开源库了. 首先,要搞明白一个问题,token.cookie.session的区别. token.cookie.session的区别 Cookie Cookie总是保存在客户端中,按在客户端中的存

JSON WEB TOKENS

用JWT来保护我们的ASP.NET Core Web API 在上一篇博客中,自己动手写了一个Middleware来处理API的授权验证,现在就采用另外一种方式来处理这个授权验证的问题,毕竟现在也 有不少开源的东西可以用,今天用的是JWT. 什么是JWT呢?JWT的全称是JSON WEB TOKENS,是一种自包含令牌格式.官方网址:https://jwt.io/,或多或少应该都有听过这个. 先来看看下面的两个图: 站点是通过RPC的方式来访问api取得资源的,当站点是直接访问api,没有拿到有

JSON Web Tokens的实现原理

前言 最近在做一个python项目的改造,将python项目重构为java项目,过程中遇到了这个知识点,觉得这个蛮实用的,所以下班后回来趁热打铁写下这篇总结,希望后面的人能够有所借鉴,少走弯路. 一.优势简介 JSON Web Tokens简称jwt,是rest接口的一种安全策略.本身有很多的优势: 解决跨域问题:这种基于Token的访问策略可以克服cookies的跨域问题. 服务端无状态可以横向扩展,Token可完成认证,无需存储Session. 系统解耦,Token携带所有的用户信息,无需绑

[Node.js] Creating JWTs (JSON Web Tokens) in Node

In this lesson we will look at all of the pieces that combine together to create a JWT (j AWT) or JSON Web Token. You will use node to create a JWT, and then verify it in the JWT debugger. What is the JSON Web Token structure? JSON Web Tokens consist

深入浅出JWT(JSON Web Token )

原文:深入浅出JWT(JSON Web Token ) 1. JWT 介绍 JSON Web Token(JWT)是一个开放式标准(RFC 7519),它定义了一种紧凑(Compact)且自包含(Self-contained)的方式,用于在各方之间以JSON对象安全传输信息. 这些信息可以通过数字签名进行验证和信任. 可以使用秘密(使用HMAC算法)或使用RSA的公钥/私钥对对JWT进行签名. 虽然JWT可以加密以提供各方之间的保密性,但我们将重点关注已签名的令牌. 签名的令牌可以验证其中包含的

Implement JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1

http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-and-identity-2/ Currently our API doesn’t support authentication and authorization, all the requests we receive to any end point are done anonymously, I

JWT(JSON Web Token) Java与.Net简单编码实现

参考 JWT(JSON WEB TOKENS)-一种无状态的认证机制 基于Token的WEB后台认证机制 各种语言版本的基于HMAC-SHA256的base64加密 Java与.Net实现实现 // java HMacsha256 private static final String MAC_INSTANCE_NAME = "HMacSHA256"; public static String Hmacsha256(String secret, String message) thro

什么是 JWT -- JSON WEB TOKEN

转自于:http://www.jianshu.com/p/576dbf44b2ae 什么是JWT Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景.JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密. 起