pom.xml文件


<!-- Base64编码时用到 --> <dependency>     <groupId>com.auth0</groupId>     <artifactId>java-jwt</artifactId>     <version>3.2.0</version> </dependency> <!-- 核心包 --> <dependency>     <groupId>io.jsonwebtoken</groupId>     <artifactId>jjwt</artifactId>     <version>0.8.0</version> </dependency>


粗略的实现类:


import java.util.Date;   import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec;   import org.bouncycastle.util.encoders.Base64;   import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.SignatureException;     public class JWTTest {       public static final String JWT_SECERT = "b3d4e546a7a94da59cb193203116c06f3acff0e258054ea0a7bce8717e44b27a";          /**      * 创建key      * @return      */     public static SecretKey generalKey() {         byte[] encodeKey = Base64.decode(JWT_SECERT);         SecretKey key = new SecretKeySpec(encodeKey, 0, encodeKey.length, "AES");         return key;     }          /**      * 签发JWT      *       * @param jti jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击      * @param sub jwt所面向的用户      * @param expiredTimeAt 过期时间(当前时间ms+要过期时间ms),单位ms      * @return      */     public static String createJWT(String jti, String sub, long expiredTimeAt) {         SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;         Long nowMillis = System.currentTimeMillis();         Date now = new Date(nowMillis);         SecretKey secretKey = generalKey();         JwtBuilder builder = Jwts.builder()                 .claim("name", "xxxx") // 自定义声明(可以定义多个,也可以不定义)                 .setId(jti)                 .setSubject(sub)                 .setIssuedAt(now) // jwt的签发时间                 .signWith(signatureAlgorithm, secretKey);         if (expiredTimeAt > 0) {             Date expDate = new Date(expiredTimeAt);             builder.setExpiration(expDate);         }         return builder.compact();     }          /**      * 校验jwtStr      *       * @param jwtStr      * @return      * @throws ExpiredJwtException,SignatureException,Exception token已过期,签名校验失败,其它错误      */     public static boolean validateJWT(String jwtStr) {         boolean flag = false;         try {             parseJWT(jwtStr);             flag = true;         } catch (ExpiredJwtException e) {             // TODO 可以用日志来记录错误信息         } catch (SignatureException e) {             // TODO 可以用日志来记录错误信息         } catch (Exception e) {             // TODO 可以用日志来记录错误信息         }         return flag;     }          /**      *       * 解析JWT字符串      *       * @param jwt      * @return claims,包括公告声明,自定义声明      * @throws ExpiredJwtException,SignatureException,Exception token已过期,签名校验失败,其它错误      */     public static Claims parseJWT(String jwt) throws ExpiredJwtException,SignatureException,Exception {         SecretKey secretKey = generalKey();         return Jwts.parser()             .setSigningKey(secretKey)             .parseClaimsJws(jwt)             .getBody();     }          public static void main(String[] args){         String jwtString = createJWT("1001", "huang", System.currentTimeMillis() + 10000);         System.out.println(jwtString);          //        Claims claims = parseJWT(jwtString); //        System.out.println(claims.getId()); //        System.out.println(claims.getSubject()); //        System.out.println(claims.get("name")); // 自定义的                  try {             System.out.println(parseJWT(jwtString));         } catch (ExpiredJwtException e) {             System.out.println("token已过期");         } catch (SignatureException e) {             System.out.println("签名校验失败");         } catch (Exception e) {             System.out.println("其它错误");         }       }   }


在JWT创建过程中,以下部分属于payload(荷载)部分



.claim("name", "xxxx") // 自定义声明(可以定义多个,也可以不定义) .setId(jti) .setSubject(sub) .setIssuedAt(now) // jwt的签发时间


其实这部分还有另外一种方式,payload应该是json的字符串形式,这个优先级别高于上面的设置方式。(本人未亲自测试过,我是看源码得出的猜测)

Jwts.builder().setPayload(payload)

以下是设置payload的一部分源码。出处DefaultJwtBuilder.class的compact()里大概303行


if (compressionCodec != null) {       byte[] bytes;     try {         bytes = this.payload != null ? payload.getBytes(Strings.UTF_8) : toJson(claims);     } catch (JsonProcessingException e) {         throw new IllegalArgumentException("Unable to serialize claims object to json.");     }       base64UrlEncodedBody = TextCodec.BASE64URL.encode(compressionCodec.compress(bytes));   } else {     base64UrlEncodedBody = this.payload != null ?             TextCodec.BASE64URL.encode(this.payload) :             base64UrlEncode(claims, "Unable to serialize claims object to json.");




重点是这句:bytes = this.payload != null ? payload.getBytes(Strings.UTF_8) : toJson(claims);

上面的JWTTest.java类写的很粗糙,有时间再改进。


--------------------------------------------------------2017年12月11日修改--------------------------------------------------------

忘记补充了,jwt一旦签发出去,不到失效时间,该token会一直生效。

如果想要手动让其失效,可以将该token保存在数据库或者缓存中。

比如存放在redis中,并同时设置失效时间,请求接收到该token后,

与redis里的token进行匹配。

--------------------------------------------------------2017年12月26日修改--------------------------------------------------------

让jwt失效还有一个办法就是更换密钥key,一旦更换会导致之前签发出去的所有jwt失效