JWT(JSON Web Token)的使用

JSON Web Token的使用

通过一段时间的摸索和参考度娘,终于完成了jwt的加密和解密操作,这里不多废话,直接上代码(保证可以运行通过):

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.Verification;
import com.fq.common.util.constants.HttpResultConstant;
import com.fq.common.util.constants.SystemConstant;
import com.fq.common.util.vo.CheckResult;
import com.sun.istack.internal.NotNull;
import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.TextCodec;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SignatureException;
import java.util.Base64;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
 * JWT官网:https://jwt.io/introduction/
 */
public class JwtUtil {
    //HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)中的secret(即常说的加盐)
    public static final String JWT_SECERT = Base64.getEncoder().encodeToString("jwt_secret".getBytes());
    //解析token,返回jwt中的部分结构
    public static final Integer PARSER_JSON_TYPE_HEADER = 1;//返回header部分
    public static final Integer PARSER_JSON_TYPE_PAYLOAD = 2;//返回payload部分
    public static final Integer PARSER_JSON_TYPE_SIGNATURE = 3;//返回signature

    /**
     * 解析JSON Web Token
     * @param returnType 返回token中的指定结构
     * @param token
     * @return 返回的是加密/编码的字符串,header、payload都是可以通过Base64解码,signature是由HMACSHA256算法创建的
     */
    public static String parseJWT(Integer returnType, String token) {
        String checkResult = "";
        if(Objects.isNull(returnType) || null==token || token.trim().equals("")){
            return checkResult;
        }
        try {
            //Base64.getDecoder().decode(JWT_SECERT),这是因为这种解析token的方式,
            // 如果直接调用Algorithm.HMAC256重构方法传入未解码的JWT_SECERT,
            // 会导致内部的JWT_SECERT.getBytes()获取到的字节数组跟调用JwtBuilder.signWith(SignatureAlgorithm.HS256, JWT_SECERT)时(内部会对JWT_SECERT解码并获取字节数组)获取的字节数组不一致,
            //从而导致解析失败
            Verification require = JWT.require(Algorithm.HMAC256(Base64.getDecoder().decode(JWT_SECERT)));
            DecodedJWT decodedJWT = require.build().verify(token);
            switch (returnType){
                case 1: return decodedJWT.getHeader();
                case 2: return decodedJWT.getPayload();
                case 3: return decodedJWT.getSignature();
                default:break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return checkResult;
    }

    /**
     *
     * 解析JSON Web Token
     * @param jwt
     * @return 返回JWT封装对象
     * @throws Exception
     */
    public static Jwt parseJWT(String jwt){
        try {
            //解析jwt的简化操作,可以看成是
            // JWT.require(Algorithm.HMAC256(Base64.getDecoder().decode(JWT_SECERT))).build().verify(token)的封装操作
            return Jwts.parser().setSigningKey(JWT_SECERT).parse(jwt);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 生成JWT
     * @param payloadMap payload声明参数
     * @param sub 面向的对象
     * @param expire 有效期(单位ms)
     * @return
     */
    public static String createJwt(Map<String, Object> payloadMap){
        return Jwts.builder()
                    .setHeader(createJwtHeader())
                    .addClaims(payloadMap)
                    .signWith(SignatureAlgorithm.HS256, JWT_SECERT)
                    .compact();
    }

    /**
     * 创建JSON Web Token header部分
     * @return
     */
    public static Map<String, Object> createJwtHeader(){
        Map<String, Object> map = new HashMap<>();
        map.put(JwsHeader.TYPE,JwsHeader.JWT_TYPE);//jwt类型
//        map.put(JwsHeader.CONTENT_TYPE,"application/json");//http请求类型
        map.put(JwsHeader.ALGORITHM, SignatureAlgorithm.HS256.getValue());//算法名称
        return map;
    }

    /**
     * 创建payload(载荷)中的声明部分
     * @param sub jwt面向对象
     * @param expire 有效时间
     * @param params 其他参数,可以是不敏感的用户信息,也可以是payload的中的信息
     * @return
     */
    public static Map<String, Object> createJwtPayload(String sub, int expire, Map<String, Object> params){
        Date issuanceDate = new Date();//签发时间
        Date expireDate = DateUtil.getExpireTime(Calendar.SECOND, expire);//有效时间
        Map<String, Object> map = new LinkedHashMap<>();
        //标准中注册的声明部分(建议但不强制参数)
        map.put(Claims.SUBJECT, sub);//jwt所面向的用户
        map.put(Claims.ISSUER,"test");//jwt签发者
        // 日期转换成秒,
        // 否则DecodedJWT jwt = new JWTDecoder(parser, token)导致解析的时候,将毫秒数当做秒来解析,造成日期错误,
        // 使得后续解析失败
        map.put(Claims.ISSUED_AT, issuanceDate.getTime()/1000);//jwt签发时间,单位s
        map.put(Claims.EXPIRATION, expireDate.getTime()/1000);//jwt过期时间,这个过期时间必须要大于签发时间,单位s
//        map.put(Claims.NOT_BEFORE, null);//定义在某个时间点之前,该jwt都是不可用的
//        map.put(Claims.ID, null);//jwt的唯一身份表示,主要用来作为一次性token,从而回避重放共计
        if(Objects.nonNull(params)){
            map.putAll(params);
        }
        return map;
    }

    public static void main(String[] args) throws Exception {
        String encodeJwt = createJwt(createJwtPayload("测试",2, null));
        System.out.println(encodeJwt);
//        Thread.sleep(3000);
//        System.out.println(parseJWT(encodeJwt).toString());
        System.out.println(parseJWT(2,encodeJwt).toString());
//        System.out.println(new String(java.util.Base64.getDecoder().decode("eyJzdWIiOiLmtYvor5UiLCJpc3MiOiJmYW5ncWkiLCJpYXQiOjE2MDU5MzEyMDIsImV4cCI6MTYwNTkzMTIwNH0")));
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值