pom.xml文件
com.auth0
java-jwt
3.2.0
io.jsonwebtoken
jjwt
0.8.0
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的签发时间
Jwts.builder().setPayload(payload)
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);
--------------------------------------------------------2017年12月11日修改--------------------------------------------------------
忘记补充了,jwt一旦签发出去,不到失效时间,该token会一直生效。
如果想要手动让其失效,可以将该token保存在数据库或者缓存中。
比如存放在redis中,并同时设置失效时间,请求接收到该token后,
与redis里的token进行匹配。
--------------------------------------------------------2017年12月26日修改--------------------------------------------------------
修改版链接:http://blog.csdn.net/h996666/article/details/78902545
让jwt失效还有一个办法就是更换密钥key,一旦更换会导致之前签发出去的所有jwt失效