package com.fdkankan.common.util; import com.auth0.jwt.JWT; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.DecodedJWT; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class JwtUtil { //生成签名的时候使用的秘钥secret private static final String SECRET = "XX#$%()(#*!()!KL<>?N<:{LWPW"; /** * 用户登录成功后生成Jwt * 使用Hs256算法 私匙使用用户密码 * * @param ttlMillis jwt过期时间 * @param userName 用户名 * @return */ public static String createJWT(long ttlMillis, String userName, String loginType) { //指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。 SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; //生成JWT的时间 long nowMillis = System.currentTimeMillis(); Date now = new Date(nowMillis); //创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的) Map claims = new HashMap(); claims.put("userName", userName); claims.put("loginType", loginType); //下面就是在为payload添加各种标准声明和私有声明了 //这里其实就是new一个JwtBuilder,设置jwt的body JwtBuilder builder = Jwts.builder() //如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的 .setClaims(claims) //设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。 .setId(UUID.randomUUID().toString()) //iat: jwt的签发时间 .setIssuedAt(now) //代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。 .setSubject(userName) //设置签名使用的签名算法和签名使用的秘钥 .signWith(signatureAlgorithm, SECRET); if (ttlMillis >= 0) { long expMillis = nowMillis + ttlMillis; Date exp = new Date(expMillis); //设置过期时间 builder.setExpiration(exp); }/*else{ //设置过期时间半小时 DateTime expDate = new DateTime().plusMinutes(30); builder.setExpiration(expDate.toDate()); }*/ return builder.compact(); } /** * Token的解密 * @param token 加密后的token * @return */ public static Claims parseJWT(String token) { //得到DefaultJwtParser Claims claims = Jwts.parser() //设置签名的秘钥 .setSigningKey(SECRET) //设置需要解析的jwt .parseClaimsJws(token).getBody(); return claims; } /** * 校验token * 在这里可以使用官方的校验,我这里校验的是token中携带的密码于数据库一致的话就校验通过 * @param token * @param userName * @return */ public static Boolean isVerify(String token, String userName) { //得到DefaultJwtParser Claims claims = Jwts.parser() //设置签名的秘钥 .setSigningKey(SECRET) //设置需要解析的jwt .parseClaimsJws(token).getBody(); if (claims.get("userName").equals(userName)) { return true; } return false; } /** * 获得token中的信息无需secret解密也能获得 * * @return token中包含的用户名 */ public static String getUsername(String token) { try { DecodedJWT jwt = JWT.decode(token); return jwt.getClaim("userName").asString(); } catch (JWTDecodeException e) { return null; } } /** * 获得token中的信息无需secret解密也能获得 * * @return token中包含的用户名 */ public static String getLoginType(String token) { try { DecodedJWT jwt = JWT.decode(token); return jwt.getClaim("loginType").asString(); } catch (JWTDecodeException e) { return null; } } public static void main(String[] args) { long start = System.currentTimeMillis(); System.out.println(getUsername("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMzExMjMxMTE3OCIsInVzZXJOYW1lIjoiMTMxMTIzMTExNzgiLCJpYXQiOjE1NjQwNDY0OTgsImp0aSI6IjhhZWJlNzhlLTU2OGUtNDY2Yi1iY2E3LWQ4ZjI0MjgxYzJhZCJ9.1N3UNjkT39mXtymfkJQVQJxOlFM3gfC6bgfur5mVmEU")); System.out.println(System.currentTimeMillis() - start); } }