Exemplo n.º 1
0
        /// <summary>
        /// 解析JWT令牌
        /// </summary>
        /// <param name="token">JWT令牌</param>
        /// <param name="claim">Claim名称</param>
        /// <returns>返回指定的Claim值,解析失败返回null</returns>
        public object Parse(string token, JwtClaimNames claim)
        {
            if (string.IsNullOrWhiteSpace(token))
            {
                throw new ArgumentException(nameof(token));
            }

            // 令牌解密
            string jwtStr;

            if (_useAes)
            {
                var jwtBytes = JwtBase64Url.Decode(token);               // 解码
                jwtStr = Encoding.UTF8.GetString(Aes.Decrypt(jwtBytes)); // 解密
            }
            else
            {
                jwtStr = token;
            }

            var parts = jwtStr.Split('.');

            if (parts.Length != 3)
            {
                throw new ArgumentOutOfRangeException(token, "令牌必须由3个由点分隔的部分组成");
            }

            // 解码负载
            var payloadDecode = JwtBase64Url.Decode(parts[1]);
            var json          = Encoding.UTF8.GetString(payloadDecode);
            var claims        = Json.Json.Deserialize <IDictionary <string, object> >(json);

            if (claims != null && claims.TryGetValue(claim.ToStr(), out var result))
            {
                return(result);
            }
            return(null);
        }
Exemplo n.º 2
0
        /// <summary>
        /// 校验JWT令牌是否有效
        /// </summary>
        /// <param name="token">JWT令牌</param>
        /// <returns>有效返回空字符串,无效返回错误</returns>
        public string Verify(string token)
        {
            string errMsg = "";

            try
            {
                if (string.IsNullOrWhiteSpace(token))
                {
                    throw new ArgumentException(nameof(token));
                }

                // 令牌解密
                string jwtStr;
                if (_useAes)
                {
                    var jwtBytes = JwtBase64Url.Decode(token);               // 解码
                    jwtStr = Encoding.UTF8.GetString(Aes.Decrypt(jwtBytes)); // 解密
                }
                else
                {
                    jwtStr = token;
                }

                var parts = jwtStr.Split('.');
                if (parts.Length != 3)
                {
                    throw new ArgumentOutOfRangeException(token, "令牌必须由3个由点分隔的部分组成");
                }

                // 验证签名
                var header  = parts[0]; // 头
                var payload = parts[1]; // 负载

                // 根据密钥和算法生成签名
                var    key            = Encoding.UTF8.GetBytes(_secret);
                var    signatureData  = $"{header}.{payload}";                 // 生成签名数据
                var    signatureBytes = Encoding.UTF8.GetBytes(signatureData); // 编码成UTF8
                byte[] signatureSha;
                switch (_algorithm)                                            // 进行签名
                {
                case JwtSecurityAlgorithms.HmacSha256: signatureSha = Hash.HSha256(key, signatureBytes); break;

                case JwtSecurityAlgorithms.HmacSha384: signatureSha = Hash.HSha384(key, signatureBytes); break;

                case JwtSecurityAlgorithms.HmacSha512: signatureSha = Hash.HSha512(key, signatureBytes); break;

                default: throw new InvalidOperationException($"不支持的签名算法[{_algorithm}]");
                }
                var signatureStr = JwtBase64Url.Encode(signatureSha);                            // 编码成Base64Url

                if (!signatureStr.Equals(parts[2], StringComparison.InvariantCultureIgnoreCase)) // 比对签名
                {
                    throw new Exception("令牌属于伪造");
                }

                return(errMsg);
            }
            catch (Exception e)
            {
                errMsg = e.Message;
            }

            return(errMsg);
        }
Exemplo n.º 3
0
        /// <summary>
        /// 生成JWT令牌
        /// </summary>
        /// <returns>返回生成的JWT令牌</returns>
        public string Build()
        {
            // JWT令牌
            var jwt = new List <string>(3);

            // 创建头部
            _header["typ"] = "JWT";                               // 类型
            _header["alg"] = _algorithm.ToStr();                  // 算法
            var headerJson  = Json.Json.Serialize(_header);       // 序列化成Json
            var headerBytes = Encoding.UTF8.GetBytes(headerJson); // 编码成UTF8
            var headerStr   = JwtBase64Url.Encode(headerBytes);   // 编码成Base64Url

            jwt.Add(headerStr);

            // 创建负载
            if (!_payload.ContainsKey(JwtClaimNames.Issuer.ToStr())) // 签发人
            {
                _payload[JwtClaimNames.Issuer.ToStr()] = "eLong.Tech";
            }
            if (!_payload.ContainsKey(JwtClaimNames.IssuedAt.ToStr())) // 颁发时间
            {
                _payload[JwtClaimNames.IssuedAt.ToStr()] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
            }
            if (!_payload.ContainsKey(JwtClaimNames.NotBefore.ToStr())) // 生效时间
            {
                _payload[JwtClaimNames.NotBefore.ToStr()] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
            }
            if (!_payload.ContainsKey(JwtClaimNames.ExpirationTime.ToStr())) // 过期时间(默认2小时)
            {
                _payload[JwtClaimNames.ExpirationTime.ToStr()] = DateTime.Now.AddHours(2).ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
            }
            _payload[JwtClaimNames.JwtId.ToStr()] = new GuidCombGenerator().NextId(); // 为Jwt指定一个UID,由于JWT令牌很长,此UID用来在Redis等缓存中标识其唯一性减少空间占用非常有用。
            var payloadJson  = Json.Json.Serialize(_payload);                         // 序列化成Json
            var payloadBytes = Encoding.UTF8.GetBytes(payloadJson);                   // 编码成UTF8
            var payloadStr   = JwtBase64Url.Encode(payloadBytes);                     // 编码成Base64Url

            jwt.Add(payloadStr);

            // 根据密钥和算法生成签名
            var key            = Encoding.UTF8.GetBytes(_secret);
            var signatureData  = string.Join(".", jwt.ToArray());       // 生成签名数据
            var signatureBytes = Encoding.UTF8.GetBytes(signatureData); // 编码成UTF8

            byte[] signatureSha;
            switch (_algorithm) // 进行签名
            {
            case JwtSecurityAlgorithms.HmacSha256: signatureSha = Hash.HSha256(key, signatureBytes); break;

            case JwtSecurityAlgorithms.HmacSha384: signatureSha = Hash.HSha384(key, signatureBytes); break;

            case JwtSecurityAlgorithms.HmacSha512: signatureSha = Hash.HSha512(key, signatureBytes); break;

            default: throw new InvalidOperationException($"不支持的签名算法[{_algorithm}]");
            }
            var signatureStr = JwtBase64Url.Encode(signatureSha); // 编码成Base64Url

            jwt.Add(signatureStr);

            // 生成令牌
            var jwtStr = string.Join(".", jwt.ToArray());

            // 返回令牌
            if (_useAes)
            {
                var jwtResult = JwtBase64Url.Encode(Aes.Encrypt(Encoding.UTF8.GetBytes(jwtStr))); // 对JWT令牌进行二次加密,防止恶意解开头和负载部分
                return(jwtResult);
            }
            else
            {
                return(jwtStr);
            }
        }