/// <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); }
/// <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); }
/// <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); } }