资讯动态

JWT(3)JWT的签名算法

发布时间:2026/10/29 19:27:32 来源:尧图企业网站定制
在JWTJSON Web Token中涉及到两种主要的算法类型加密算法和签名算法。签名算法用于确保 JWT 数据的完整性和真实性必须使用而加密算法用于保护 JWT 内容的机密性选择性使用。这里看下签名算法。介绍1、简介签名算法的主要目的是确保 JWT 的内容未被篡改并验证其来源。签名算法用于生成一个数字签名接收方使用相同的算法来验证签名从而确认数据的完整性。2、jwt常见的签名算法不同的jwt插件有不同的加密算法名称原理都一样1auth0插件// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package com.auth0.jwt.algorithms; import com.auth0.jwt.exceptions.SignatureGenerationException; import com.auth0.jwt.exceptions.SignatureVerificationException; import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.ECDSAKeyProvider; import com.auth0.jwt.interfaces.RSAKeyProvider; import java.security.interfaces.ECKey; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; public abstract class Algorithm { private final String name; private final String description; public static Algorithm RSA256(RSAKeyProvider keyProvider) throws IllegalArgumentException { return new RSAAlgorithm(RS256, SHA256withRSA, keyProvider); } public static Algorithm RSA256(RSAPublicKey publicKey, RSAPrivateKey privateKey) throws IllegalArgumentException { return RSA256(RSAAlgorithm.providerForKeys(publicKey, privateKey)); } /** deprecated */ Deprecated public static Algorithm RSA256(RSAKey key) throws IllegalArgumentException { RSAPublicKey publicKey key instanceof RSAPublicKey ? (RSAPublicKey)key : null; RSAPrivateKey privateKey key instanceof RSAPrivateKey ? (RSAPrivateKey)key : null; return RSA256(publicKey, privateKey); } public static Algorithm RSA384(RSAKeyProvider keyProvider) throws IllegalArgumentException { return new RSAAlgorithm(RS384, SHA384withRSA, keyProvider); } public static Algorithm RSA384(RSAPublicKey publicKey, RSAPrivateKey privateKey) throws IllegalArgumentException { return RSA384(RSAAlgorithm.providerForKeys(publicKey, privateKey)); } /** deprecated */ Deprecated public static Algorithm RSA384(RSAKey key) throws IllegalArgumentException { RSAPublicKey publicKey key instanceof RSAPublicKey ? (RSAPublicKey)key : null; RSAPrivateKey privateKey key instanceof RSAPrivateKey ? (RSAPrivateKey)key : null; return RSA384(publicKey, privateKey); } public static Algorithm RSA512(RSAKeyProvider keyProvider) throws IllegalArgumentException { return new RSAAlgorithm(RS512, SHA512withRSA, keyProvider); } public static Algorithm RSA512(RSAPublicKey publicKey, RSAPrivateKey privateKey) throws IllegalArgumentException { return RSA512(RSAAlgorithm.providerForKeys(publicKey, privateKey)); } /** deprecated */ Deprecated public static Algorithm RSA512(RSAKey key) throws IllegalArgumentException { RSAPublicKey publicKey key instanceof RSAPublicKey ? (RSAPublicKey)key : null; RSAPrivateKey privateKey key instanceof RSAPrivateKey ? (RSAPrivateKey)key : null; return RSA512(publicKey, privateKey); } public static Algorithm HMAC256(String secret) throws IllegalArgumentException { return new HMACAlgorithm(HS256, HmacSHA256, secret); } public static Algorithm HMAC384(String secret) throws IllegalArgumentException { return new HMACAlgorithm(HS384, HmacSHA384, secret); } public static Algorithm HMAC512(String secret) throws IllegalArgumentException { return new HMACAlgorithm(HS512, HmacSHA512, secret); } public static Algorithm HMAC256(byte[] secret) throws IllegalArgumentException { return new HMACAlgorithm(HS256, HmacSHA256, secret); } public static Algorithm HMAC384(byte[] secret) throws IllegalArgumentException { return new HMACAlgorithm(HS384, HmacSHA384, secret); } public static Algorithm HMAC512(byte[] secret) throws IllegalArgumentException { return new HMACAlgorithm(HS512, HmacSHA512, secret); } public static Algorithm ECDSA256(ECDSAKeyProvider keyProvider) throws IllegalArgumentException { return new ECDSAAlgorithm(ES256, SHA256withECDSA, 32, keyProvider); } public static Algorithm ECDSA256(ECPublicKey publicKey, ECPrivateKey privateKey) throws IllegalArgumentException { return ECDSA256(ECDSAAlgorithm.providerForKeys(publicKey, privateKey)); } /** deprecated */ Deprecated public static Algorithm ECDSA256(ECKey key) throws IllegalArgumentException { ECPublicKey publicKey key instanceof ECPublicKey ? (ECPublicKey)key : null; ECPrivateKey privateKey key instanceof ECPrivateKey ? (ECPrivateKey)key : null; return ECDSA256(publicKey, privateKey); } public static Algorithm ECDSA384(ECDSAKeyProvider keyProvider) throws IllegalArgumentException { return new ECDSAAlgorithm(ES384, SHA384withECDSA, 48, keyProvider); } public static Algorithm ECDSA384(ECPublicKey publicKey, ECPrivateKey privateKey) throws IllegalArgumentException { return ECDSA384(ECDSAAlgorithm.providerForKeys(publicKey, privateKey)); } /** deprecated */ Deprecated public static Algorithm ECDSA384(ECKey key) throws IllegalArgumentException { ECPublicKey publicKey key instanceof ECPublicKey ? (ECPublicKey)key : null; ECPrivateKey privateKey key instanceof ECPrivateKey ? (ECPrivateKey)key : null; return ECDSA384(publicKey, privateKey); } public static Algorithm ECDSA512(ECDSAKeyProvider keyProvider) throws IllegalArgumentException { return new ECDSAAlgorithm(ES512, SHA512withECDSA, 66, keyProvider); } public static Algorithm ECDSA512(ECPublicKey publicKey, ECPrivateKey privateKey) throws IllegalArgumentException { return ECDSA512(ECDSAAlgorithm.providerForKeys(publicKey, privateKey)); } /** deprecated */ Deprecated public static Algorithm ECDSA512(ECKey key) throws IllegalArgumentException { ECPublicKey publicKey key instanceof ECPublicKey ? (ECPublicKey)key : null; ECPrivateKey privateKey key instanceof ECPrivateKey ? (ECPrivateKey)key : null; return ECDSA512(publicKey, privateKey); } public static Algorithm none() { return new NoneAlgorithm(); } protected Algorithm(String name, String description) { this.name name; this.description description; } public String getSigningKeyId() { return null; } public String getName() { return this.name; } String getDescription() { return this.description; } public String toString() { return this.description; } public abstract void verify(DecodedJWT var1) throws SignatureVerificationException; public byte[] sign(byte[] headerBytes, byte[] payloadBytes) throws SignatureGenerationException { byte[] contentBytes new byte[headerBytes.length 1 payloadBytes.length]; System.arraycopy(headerBytes, 0, contentBytes, 0, headerBytes.length); contentBytes[headerBytes.length] 46; System.arraycopy(payloadBytes, 0, contentBytes, headerBytes.length 1, payloadBytes.length); return this.sign(contentBytes); } /** deprecated */ Deprecated public abstract byte[] sign(byte[] var1) throws SignatureGenerationException; }2jjwt插件io.jsonwebtoken.SignatureAlgorithmNONE(none, No digital signature or MAC performed, None, (String)null, false, 0, 0), HS256(HS256, HMAC using SHA-256, HMAC, HmacSHA256, true, 256, 256, 1.2.840.113549.2.9), HS384(HS384, HMAC using SHA-384, HMAC, HmacSHA384, true, 384, 384, 1.2.840.113549.2.10), HS512(HS512, HMAC using SHA-512, HMAC, HmacSHA512, true, 512, 512, 1.2.840.113549.2.11), RS256(RS256, RSASSA-PKCS-v1_5 using SHA-256, RSA, SHA256withRSA, true, 256, 2048), RS384(RS384, RSASSA-PKCS-v1_5 using SHA-384, RSA, SHA384withRSA, true, 384, 2048), RS512(RS512, RSASSA-PKCS-v1_5 using SHA-512, RSA, SHA512withRSA, true, 512, 2048), ES256(ES256, ECDSA using P-256 and SHA-256, ECDSA, SHA256withECDSA, true, 256, 256), ES384(ES384, ECDSA using P-384 and SHA-384, ECDSA, SHA384withECDSA, true, 384, 384), ES512(ES512, ECDSA using P-521 and SHA-512, ECDSA, SHA512withECDSA, true, 512, 521), PS256(PS256, RSASSA-PSS using SHA-256 and MGF1 with SHA-256, RSA, RSASSA-PSS, false, 256, 2048), PS384(PS384, RSASSA-PSS using SHA-384 and MGF1 with SHA-384, RSA, RSASSA-PSS, false, 384, 2048), PS512(PS512, RSASSA-PSS using SHA-512 and MGF1 with SHA-512, RSA, RSASSA-PSS, false, 512, 2048);3、签名算法分类1对称加密HMAC类属于对称加密这些算法使用同一个密钥secret_key进行签名和验证属于对称加密。一旦密钥泄露安全性就会受到威胁。适用于信任的系统内部例如单体应用或集中式认证服务。2非对称加密RSA类和ECDSA类算法属于非对称加密使用一对密钥公钥用于验证私钥用于签名提供了更好的密钥管理和分发机制即使公钥被泄露只要私钥保持安全Token依然是安全的。适用于分布式系统和多服务环境。如我们项目曾经将HS256升级为ES256。比较1性能对称加密算法通常比非对称加密算法更快但在分布式系统中非对称加密算法尤其是ECDSA更受欢迎因为它们提供了更好的安全性和灵活性。如我们项目曾将jwt由HS256HMAC SHA-256升级为ES256ECDSA SHA-256。2Token大小非对称加密算法生成的签名通常比对称加密算法的签名要大但ECDSA算法由于其较短的签名长度可以在保持安全性的同时减少Token的大小。在选择JWT的加密算法时需要根据系统的具体需求和安全要求来决定使用哪种算法。对于需要跨多个服务或不信任环境传输的Token推荐使用非对称加密算法如RS256或ES256。4、工作原理1签名生成JWT 的Header和Payload被编码为 Base64Url 格式。然后使用指定的签名算法例如HS256、RS256等生成签名。生成的签名会附加到 JWT 的最后形成 JWT 令牌。2签名验证接收方使用相应的签名算法和密钥对称密钥或公钥来验证 JWT 是否未被篡改。如果签名匹配则证明数据完整且来自授权方否则数据可能已经被篡改或伪造。一、对称加密--HMAC算法Hash-based Message Authentication Code1、HS2561.1、介绍HS256算法使用了HMAC-SHA256算法其中HMAC代表散列消息认证码SHA256是一种散列函数能够为任意长度的数据生成一个固定长度的摘要。HS256的工作原理是使用一个密钥和一个消息作为输入使用SHA-256散列函数来计算消息的摘要使用HMAC散列消息认证码函数结合散列函数和密钥来生成一个密钥相关的摘要。1.2、demopackage com.demo.security.util; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import com.demo.security.constant.UserConstants; import com.demo.security.entity.UserEntity; import lombok.extern.slf4j.Slf4j; import java.util.Date; import java.util.Map; Slf4j public class JwtUtilTest { public static void main(String[] args) { //1、生成token String username zs; Integer age 18; String key 123456; Algorithm algorithm Algorithm.HMAC256(key); UserEntity userEntity UserEntity.builder() .username(username) .age(age) .build(); String token getToken(userEntity,algorithm); log.info(token获取成功:{},token); log.info(token长度:{},token.length()); //2、验证token因为只要token是jwt第三步一定会成功这里是为了验证是不是我生成的防止攻击 JWTVerifier verifier JWT.require(algorithm).build(); verifier.verify(token); //3、解析token UserEntity tokenUser getUser(token); if(username.equals(tokenUser.getUsername())){ log.info(解析成功); } } public static UserEntity getUser( String token) { try { DecodedJWT jwt JWT.decode(token); MapString, Claim claims jwt.getClaims(); String username claims.get(username).asString(); int age claims.get(age).asInt(); return UserEntity.builder() .username(username) .age(age) .build(); } catch (JWTDecodeException e) { return null; } } /** * 生成签名,5min(分钟)后过期 * return 加密的token */ public static String getToken(UserEntity userEntity, Algorithm algorithm) { Date date new Date(System.currentTimeMillis() UserConstants.EXPIRE_TIME); // 附带username信息 return JWT.create() //iss签发方 .withIssuer(wtyy) //aud接收jwt的一方 .withAudience(web-demo) //expjwt的过期时间这个过期时间必须要大于签发时间 //.withExpiresAt() //其他自定义通信信息 .withClaim(username, userEntity.getUsername()) .withClaim(age,userEntity.getAge()) .withExpiresAt(date) .sign(algorithm); } }执行打印14:50:25.610 [main] INFO com.demo.security.util.JwtUtilTest -- token获取成功:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJ3ZWItZGVtbyIsImlzcyI6Ind0eXkiLCJleHAiOjE3MjEzNzM2MjUsImFnZSI6MTgsInVzZXJuYW1lIjoienMifQ.9dEWE3Q6zBa6szo1QVv5UaGfeXMsWyCJ64RSnWFx1Ns 14:50:25.624 [main] INFO com.demo.security.util.JwtUtilTest -- token长度:179 14:50:25.645 [main] INFO com.demo.security.util.JwtUtilTest -- 解析成功通过在线解析这里为了证明第二步verify的重要性改下代码public static void main(String[] args) { //1、生成token String username zs; Integer age 18; String key 123456; Algorithm algorithm Algorithm.HMAC256(key); UserEntity userEntity UserEntity.builder() .username(username) .age(age) .build(); String token getToken(userEntity,algorithm); log.info(token获取成功:{},token); log.info(token长度:{},token.length()); //2、验证token因为只要token是jwt第三步一定会成功这里是为了验证是不是我生成的防止攻击 try{ Algorithm errorAlgorithm Algorithm.HMAC256(keyerror); JWTVerifier verifier JWT.require(errorAlgorithm).build(); verifier.verify(token); }catch (Exception e){ //throw异常 log.error(验证失败); } //3、解析token UserEntity tokenUser getUser(token); if(username.equals(tokenUser.getUsername())){ log.info(解析成功name{},tokenUser.getUsername()); } }打印15:48:42.922 [main] INFO com.demo.security.util.JwtUtilTest -- token获取成功:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJ3ZWItZGVtbyIsImlzcyI6Ind0eXkiLCJleHAiOjE3MjEzNzcxMjIsImFnZSI6MTgsInVzZXJuYW1lIjoienMifQ.mVQ5cO-nPo1SSw0qhXFdDbjQK4WdKSLmLjFWSkt8fQQ 15:48:42.924 [main] INFO com.demo.security.util.JwtUtilTest -- token长度:179 15:48:42.943 [main] ERROR com.demo.security.util.JwtUtilTest -- 验证失败 15:48:42.944 [main] INFO com.demo.security.util.JwtUtilTest -- 解析成功namezs2、HS3842.1、介绍使用SHA-384算法进行HMAC签名。2.2、demo上面的代码修改为Algorithm algorithm Algorithm.HMAC384(secret);执行打印14:55:46.167 [main] INFO com.demo.security.util.JwtUtilTest -- token获取成功:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJhdWQiOiJ3ZWItZGVtbyIsImlzcyI6Ind0eXkiLCJleHAiOjE3MjEzNzM5NDYsImFnZSI6MTgsInVzZXJuYW1lIjoienMifQ.wB0LaglQH_IcFKHa7oLm5r2Gof2DzCS0XmhvYC0m9q5nk4T4-CCTCpGllyc3waPR 14:55:46.167 [main] INFO com.demo.security.util.JwtUtilTest -- token长度:200 14:55:46.183 [main] INFO com.demo.security.util.JwtUtilTest -- 解析成功3、HS5123.1、介绍使用SHA-512算法进行HMAC签名。3.2、demo上面的代码修改为Algorithm algorithm Algorithm.HMAC512(secret);执行输出14:57:29.979 [main] INFO com.demo.security.util.JwtUtilTest -- token获取成功:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJhdWQiOiJ3ZWItZGVtbyIsImlzcyI6Ind0eXkiLCJleHAiOjE3MjEzNzQwNDksImFnZSI6MTgsInVzZXJuYW1lIjoienMifQ.J7-tJFmjP6Pnh9djMI6MnAEIFKK0Vvzn-ASVFRTWUf3kHa-NDOmYydP4jRDitui2EJNfxLu4taOo5YWZXYJoSQ 14:57:29.979 [main] INFO com.demo.security.util.JwtUtilTest -- token长度:222 14:57:29.994 [main] INFO com.demo.security.util.JwtUtilTest -- 解析成功二、非对称算法--RSA算法Rivest–Shamir–Adleman1、RS2561.1、介绍使用RSA和SHA-256算法进行签名。1.2、demo上面的代码修改为package com.demo.security.util; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import com.demo.security.constant.UserConstants; import com.demo.security.entity.UserEntity; import lombok.extern.slf4j.Slf4j; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.Date; import java.util.Map; Slf4j public class JwtUtilTest { public static void main(String[] args) throws Exception { //1、先生成公钥私钥 KeyPairGenerator keyGen KeyPairGenerator.getInstance(RSA); keyGen.initialize(2048); KeyPair pair keyGen.generateKeyPair(); RSAPrivateKey rsaPrivateKey (RSAPrivateKey) pair.getPrivate(); RSAPublicKey rsaPublicKey (RSAPublicKey) pair.getPublic(); //2、根据私钥生成jwt String username zs; Integer age 18; UserEntity userEntity UserEntity.builder() .username(username) .age(age) .build(); String token getToken(userEntity,rsaPrivateKey,rsaPublicKey); log.info(token获取成功:{},token); log.info(token长度:{},token.length()); //3、先验证是否合法注意第四步是一定可以成功的这里是为了安全验证校验token是不是我生成的防止攻击 Algorithm algorithm Algorithm.RSA256(rsaPublicKey, null); JWTVerifier verifier JWT.require(algorithm).build(); //公钥验证不通过会抛异常 verifier.verify(token); //log.info(验证成功); //4、根据公钥解析jwt UserEntity tokenUser getUser(token); if(username.equals(tokenUser.getUsername())){ log.info(解析成功); } } public static UserEntity getUser( String token) { try { DecodedJWT jwt JWT.decode(token); MapString, Claim claims jwt.getClaims(); String username claims.get(username).asString(); int age claims.get(age).asInt(); return UserEntity.builder() .username(username) .age(age) .build(); } catch (JWTDecodeException e) { return null; } } /** * 生成签名,5min(分钟)后过期 * param rsaPrivateKey * param rsaPublicKey * return 加密的token */ public static String getToken(UserEntity userEntity, RSAPrivateKey rsaPrivateKey, RSAPublicKey rsaPublicKey) throws Exception { Date date new Date(System.currentTimeMillis() UserConstants.EXPIRE_TIME); Algorithm algorithm Algorithm.RSA256(rsaPublicKey,rsaPrivateKey); // 附带username信息 return JWT.create() //iss签发方 .withIssuer(wtyy) //aud接收jwt的一方 .withAudience(web-demo) //expjwt的过期时间这个过期时间必须要大于签发时间 //.withExpiresAt() //其他自定义通信信息 .withClaim(username, userEntity.getUsername()) .withClaim(age,userEntity.getAge()) .withExpiresAt(date) .sign(algorithm); } private static RSAPublicKey convertStringToRSAPublicKey(String publicKeyString) throws Exception { publicKeyString publicKeyString.replaceAll(\\n, ) .replace(-----BEGIN PUBLIC KEY-----, ) .replace(-----END PUBLIC KEY-----, ); // base64 decode byte[] publicKeyBytes Base64.getDecoder().decode(publicKeyString); // X509EncodedKeySpec change to PublicKey X509EncodedKeySpec keySpec new X509EncodedKeySpec(publicKeyBytes); KeyFactory keyFactory KeyFactory.getInstance(RSA); PublicKey publicKey keyFactory.generatePublic(keySpec); // change PublicKey to RSAPublicKey return (RSAPublicKey) publicKey; } }执行打印15:39:47.174 [main] INFO com.demo.security.util.JwtUtilTest -- token获取成功:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJ3ZWItZGVtbyIsImlzcyI6Ind0eXkiLCJleHAiOjE3MjEzNzY1ODcsImFnZSI6MTgsInVzZXJuYW1lIjoienMifQ.ERWm_kHMzFyEnrgaRC1TX19tmdalidKZ3h-SSrRkMuMmvYghFSsKWkIpvrhcXN-vtigweUThjg7IbHvS8unWV11Z6eb8vHldlq6kXnrTl802oEQqr6ORRnMafmxqEX7KqQsv7vv0JDwLbf8xEM4gebJqU_fKBOtw5mKivKt2fmZXs4vrBFHU_OXex4cUZp1TdMEAhJeysRhFGcLHqctgTkqx7NIUj80cODTMPfv2HNUJu-nZ5vn5oCmOkhD9yB5A3lpc7DM_qDL57jRQazoQMyTg97P9p_5x5qzI4mQNEqlnJyhJ9U-sqVsyFka_JiehyHJn_CEtpR031MFw0mUd-g 15:39:47.176 [main] INFO com.demo.security.util.JwtUtilTest -- token长度:478 15:39:47.199 [main] INFO com.demo.security.util.JwtUtilTest -- 解析成功为了验证第三步的重要性改下代码//3、先验证是否合法注意第四步是一定可以成功的这里是为了安全验证校验token是不是我生成的防止攻击 try{ Algorithm algorithm Algorithm.RSA256(null, null); JWTVerifier verifier JWT.require(algorithm).build(); //公钥验证不通过会抛异常 verifier.verify(token); }catch (Exception e){ log.error(验证失败); } //4、根据公钥解析jwt UserEntity tokenUser getUser(token); if(username.equals(tokenUser.getUsername())){ log.info(解析成功,name{},tokenUser.getUsername()); } 这两步打印 15:42:19.882 [main] ERROR com.demo.security.util.JwtUtilTest -- 验证失败 15:42:19.905 [main] INFO com.demo.security.util.JwtUtilTest -- 解析成功,namezs2、RS384使用RSA和SHA-384算法进行签名。上面的代码修改下256改成384执行下输出15:51:33.549 [main] INFO com.demo.security.util.JwtUtilTest -- token获取成功:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzM4NCJ9.eyJhdWQiOiJ3ZWItZGVtbyIsImlzcyI6Ind0eXkiLCJleHAiOjE3MjEzNzcyOTMsImFnZSI6MTgsInVzZXJuYW1lIjoienMifQ.lWIWB72Xnm3Gxdoa6TTM2g7SrgDY3m3sn1TShQPJrpyXm_Z9pnv9qup3yAvUmGyR2HbsqsjX9mG6kMz5A3Rxuvl2icIA0TzSq3SD4X0CWg6yOa1CO76W9yEHvFewPkYNfDNx1gHwcmyLW4PavcZaOnpMrOfILaVoqUeoaJ9d5fye39ASLbsgj76JL1KdX7EaM3eb_x3DPp7zt46rsV76z5IGlXnxAch4va5zF3h73Pj6HmbQ6g9FDCPa9Kz3Yd9PlxKm9lWTDMTNrEZ0Dphgi7mxs2XLJoYIfJEY9_jqLeFkl2otFLTAURoS_sNrOvQMtXRkDPoraIi5gfM-IyUnJA 15:51:33.551 [main] INFO com.demo.security.util.JwtUtilTest -- token长度:478 15:51:33.573 [main] INFO com.demo.security.util.JwtUtilTest -- 解析成功3、RS512使用RSA和SHA-512算法进行签名。上面的代码修改下384改成512执行下输出15:52:24.816 [main] INFO com.demo.security.util.JwtUtilTest -- token获取成功:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJhdWQiOiJ3ZWItZGVtbyIsImlzcyI6Ind0eXkiLCJleHAiOjE3MjEzNzczNDQsImFnZSI6MTgsInVzZXJuYW1lIjoienMifQ.sC5D9qDnJg4fvtg3M9MSlJqZ2K7t88yFaP4-KWLyd5Y5Tm-PlwJImLtT3g2NwW-NGnmUpVZ0nYY47io49FN7IYKRv7NxpniAwWOc-JBJM1o2SeGAsG_dPBfdOxB4_6f1V5gMiDuqHIdyjW7DPl3w72j2-etjXg4xBG0ed-LihzZ7MWhWreEoPoBSJja8CDalE0bXAAHQn3EKvlbAlTO7QLdOpJvM1cQJlBMTzaes8sXbc-yqY-lQ7LOtKbqdd90d_muBUq5Qn4bjO5GWcq-QGTjzSXvQH-ttKJliVblvJYpCMs0mAFIniL41lKTNNVg3G-zRcFJtwtdOUSYMEadEIA 15:52:24.818 [main] INFO com.demo.security.util.JwtUtilTest -- token长度:478 15:52:24.839 [main] INFO com.demo.security.util.JwtUtilTest -- 解析成功三、非对称--ECDSA算法Elliptic Curve Digital Signature Algorithm特点与RSA算法类似ECDSA也是非对称加密算法但使用的是椭圆曲线加密通常比RSA算法更快签名和验证过程更高效。同时ECDSA的密钥长度较短有助于减少Token的大小。1、ES256使用椭圆曲线加密算法ECDSA和SHA-256进行签名。demopackage com.demo.security.util; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import com.demo.security.constant.UserConstants; import com.demo.security.entity.UserEntity; import lombok.extern.slf4j.Slf4j; import java.security.*; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.ECGenParameterSpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.Date; import java.util.Map; Slf4j public class JwtUtilTest { public static void main(String[] args) throws Exception { //1、先生成公钥私钥 // 初始化KeyPairGenerator KeyPairGenerator keyPairGenerator KeyPairGenerator.getInstance(EC); // 设置ECDSA使用的椭圆曲线为secp256r1 ECGenParameterSpec ecSpec new ECGenParameterSpec(secp256r1); keyPairGenerator.initialize(ecSpec); KeyPair pair keyPairGenerator.generateKeyPair(); ECPrivateKey ecPrivateKey (ECPrivateKey) pair.getPrivate(); ECPublicKey ecPublicKey (ECPublicKey) pair.getPublic(); //2、根据私钥生成jwt String username zs; Integer age 18; UserEntity userEntity UserEntity.builder() .username(username) .age(age) .build(); String token getToken(userEntity,ecPrivateKey,ecPublicKey); log.info(token获取成功:{},token); log.info(token长度:{},token.length()); //3、先验证是否合法注意第四步是一定可以成功的这里是为了安全验证校验token是不是我生成的防止攻击 Algorithm algorithm Algorithm.ECDSA256(ecPublicKey, null); JWTVerifier verifier JWT.require(algorithm).build(); //公钥验证不通过会抛异常 verifier.verify(token); log.info(验证成功); //4、根据公钥解析jwt UserEntity tokenUser getUser(token); if(username.equals(tokenUser.getUsername())){ log.info(解析成功); } } public static UserEntity getUser( String token) { try { DecodedJWT jwt JWT.decode(token); MapString, Claim claims jwt.getClaims(); String username claims.get(username).asString(); int age claims.get(age).asInt(); return UserEntity.builder() .username(username) .age(age) .build(); } catch (JWTDecodeException e) { return null; } } /** * 生成签名,5min(分钟)后过期 * param rsaPrivateKey * param rsaPublicKey * return 加密的token */ public static String getToken(UserEntity userEntity, ECPrivateKey rsaPrivateKey, ECPublicKey rsaPublicKey) throws Exception { Date date new Date(System.currentTimeMillis() UserConstants.EXPIRE_TIME); Algorithm algorithm Algorithm.ECDSA256(rsaPublicKey,rsaPrivateKey); // 附带username信息 return JWT.create() //iss签发方 .withIssuer(wtyy) //aud接收jwt的一方 .withAudience(web-demo) //expjwt的过期时间这个过期时间必须要大于签发时间 //.withExpiresAt() //其他自定义通信信息 .withClaim(username, userEntity.getUsername()) .withClaim(age,userEntity.getAge()) .withExpiresAt(date) .sign(algorithm); } }执行输出16:00:37.510 [main] INFO com.demo.security.util.JwtUtilTest -- token获取成功:eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJ3ZWItZGVtbyIsImlzcyI6Ind0eXkiLCJleHAiOjE3MjEzNzc4MzcsImFnZSI6MTgsInVzZXJuYW1lIjoienMifQ.niLzXGc3kuiYm75UrbCtK9qUTdDIUyo89nLkb1tOyH1dE--G_IILabMFsOlYHgTdx-z_zoJFjHqtlaIYXXdD8w 16:00:37.512 [main] INFO com.demo.security.util.JwtUtilTest -- token长度:222 16:00:37.538 [main] INFO com.demo.security.util.JwtUtilTest -- 验证成功 16:00:37.540 [main] INFO com.demo.security.util.JwtUtilTest -- 解析成功通过在线解析2、ES384使用ECDSA和SHA-384进行签名。3、ES512使用ECDSA和SHA-512进行签名。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑