JJWT应用到前后端分离项目或JSP页面项目中的登录、加签、验签、登出、自动化续签

 

项目背景:

该项目是一个给用户使用的客户端,由于时间比较紧,而且需要考虑到组内开发学习成本所以直接使用的轻量级JWT,并没有使用spring security和OAuth2等;该项目使用技术点:springBoot、spring mvc、mybatis、Spring admin、actuactor、swagger、swaggerdocs等常用技术

 

因为jwt无法对token进行内部登出以及内部自动化续签(内部登出与内部自动化续签是指前端在不改变token的情况下进行销毁token和延长token有效期),基于此项目在服务内部做了这些处理以及前端vue针对自动化续签的结果进行更替以及继续请求原有的请求

1、首先进行登录:

登录api:

 

这里使用的是公私钥的方式,当然使用何种加密方式无所谓,自己根据jjwt官网首页做修改都可以


import com.sioo.sioohyclient.common.constants.JWTConstants;
import com.sioo.sioohyclient.common.model.UserInfo;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ObjectUtils;
import org.joda.time.DateTime;

import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.Date;

/**
* @Description: JWT工具类
* @Param:
* @return:
* @Author: fanghuaiming
* @Date:
*/
@Slf4j
public class JWTUtils {
    /**
     * 私钥加密token
     *
     * @param userInfo 载荷中的数据
     * @param privateKey 私钥
     * @param expireMinutes 过期时间,单位分
     * @return
     */
    public static String generateToken(UserInfo userInfo, PrivateKey privateKey,int expireMinutes){
        return Jwts.builder()
                .claim(JWTConstants.JWT_KWT_USER_NAME,userInfo.getUserName())
                .claim(JWTConstants.JWT_KWT_Uid,userInfo.getUid())
                .claim(JWTConstants.JWT_KWT_PRICE,userInfo.getPrice())
                .claim(JWTConstants.JWT_KWT_SHOWRPT,userInfo.getShowRpt())
                .claim(JWTConstants.JWT_KWT_ISNEW,userInfo.getIsNew())
                .claim(JWTConstants.JWT_KWT_APIRPT,userInfo.getApiRpt())
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
                .signWith(SignatureAlgorithm.RS256,privateKey)
                .compact();
    }

    /**
     * 私钥加密token
     *
     * @param userInfo 载荷中的数据
     * @param privateKey 私钥字节数组
     * @param expireMinutes 过期时间,单位秒
     * @return
     */
    public static String generateToken(UserInfo userInfo,byte[] privateKey,int expireMinutes) throws Exception {
        return Jwts.builder()
                .claim(JWTConstants.JWT_KWT_USER_NAME,userInfo.getUserName())
                .claim(JWTConstants.JWT_KWT_Uid,userInfo.getUid())
                .claim(JWTConstants.JWT_KWT_PRICE,userInfo.getPrice())
                .claim(JWTConstants.JWT_KWT_SHOWRPT,userInfo.getShowRpt())
                .claim(JWTConstants.JWT_KWT_ISNEW,userInfo.getIsNew())
                .claim(JWTConstants.JWT_KWT_APIRPT,userInfo.getApiRpt())
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
                .signWith(SignatureAlgorithm.RS256, RsaUtils.getPrivateKey(privateKey))
                .compact();

    }

    /**
     * 公钥解析token
     *
     * @param token 用户请求中的token
     * @param publicKey 公钥
     * @return
     */
    private static Jws<Claims> parserToken(String token, PublicKey publicKey){
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    }

    /**
     * 公钥解析token
     *
     * @param token 用户请求中的token
     * @param publicKey 公钥字节数组
     * @return
     * @throws InvalidKeySpecException
     * @throws NoSuchAlgorithmException
     */
    private static Jws<Claims> parserToken(String token,byte[] publicKey) throws Exception {
        return Jwts.parser().setSigningKey(RsaUtils.getPublicKey(publicKey))
                .parseClaimsJws(token);
    }

    /**
     * 获取token中的用户信息
     *
     * @param token 用户请求中的令牌
     * @param publicKey 公钥
     * @return 用户信息
     */
    public static UserInfo getInfoFromToken(String token,PublicKey publicKey){
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();

        return new UserInfo(
          ObjectUtils.toString(body.get(JWTConstants.JWT_KWT_USER_NAME)),
                (Integer)body.get(JWTConstants.JWT_KWT_Uid),
                (double)body.get(JWTConstants.JWT_KWT_PRICE),
                (Integer)body.get(JWTConstants.JWT_KWT_SHOWRPT),
                (Integer)body.get(JWTConstants.JWT_KWT_ISNEW),
                (Integer)body.get(JWTConstants.JWT_KWT_APIRPT)
        );
    }

    /**
     * 获取token中的用户信息
     *
     * @param token 用户请求中的令牌
     * @param publicKey 公钥字节数组
     * @return
     * @throws InvalidKeySpecException
     * @throws NoSuchAlgorithmException
     */
    public static UserInfo getInfoFromtoken(String token,byte[] publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        return new UserInfo(
                ObjectUtils.toString(body.get(JWTConstants.JWT_KWT_USER_NAME)),
                (Integer)body.get(JWTConstants.JWT_KWT_Uid),
                (double)body.get(JWTConstants.JWT_KWT_PRICE),
                (Integer)body.get(JWTConstants.JWT_KWT_SHOWRPT),
                (Integer)body.get(JWTConstants.JWT_KWT_ISNEW),
                (Integer)body.get(JWTConstants.JWT_KWT_APIRPT)
        );
    }

    /**
    * @Description: 获取当前token的有效期设置
    * @Param:
    * @return:
    * @Author: fanghuaiming
    * @Date: 1:59 PM 2019/7/29
    */
    public static Date getExpirationDateFromToken(String token,PublicKey publicKey) {
        //获取当前token的body
        Claims body = parserToken(token, publicKey).getBody();
        //获取当前token的有效期
        return body.getExpiration();
    }


    /** 
    * @Description: 是否已经过期
    * @Param:
    * @return:
    * @Author: fanghuaiming
    * @Date: 2:01 PM 2019/7/29
    */
    public static Boolean isTokenExpired(String token, PublicKey publicKey) {
        try {
            final Date expiration = getExpirationDateFromToken(token,publicKey);
            return expiration.before(new Date());
        } catch (ExpiredJwtException expiredJwtException) {
            log.error("查看token是否已经过期发生异常,异常内容:{}",expiredJwtException.getMessage());
            return true;
        }
    }

}

涉及到的相关方法和配置:

/**
* @Description: jwt使用的constants常量
* @Param:
* @return:
* @Author: fanghuaiming
* @Date:
*/
public abstract class JWTConstants {

    /**
     * 用户名
     */
    public static final String JWT_KWT_USER_NAME = "userName";

    /**
     * 用户id
     */
    public static final String JWT_KWT_Uid = "uid";

    /**
     * 用户单价
     */
    public static final String JWT_KWT_PRICE = "price";

    /**
     * 用户前台是否显示报告
     */
    public static final String JWT_KWT_SHOWRPT= "showRpt";

    /**
     * 用户是否新用户
     */
    public static final String JWT_KWT_ISNEW= "isNew";

    /**
     * 是否开通接口状态:0为开通,1为不开通
     */
    public static final String JWT_KWT_APIRPT= "apiRpt";
}
import com.sioo.sioohyclient.common.utils.RsaUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;

import javax.annotation.PostConstruct;
import java.io.File;
import java.security.PrivateKey;
import java.security.PublicKey;

/**
* @Description: JWT相关配置
* @Param:
* @return:
* @Author: fanghuaiming
* @Date:
*/
@ConfigurationProperties(prefix = "siooclient.jwt")
public class JwtProperties {

    /**
     *  密钥
     */
    private String secret;

    /**
     *  公钥地址
     */
    private String pubKeyPath;

    /**
     *  私钥地址
     */
    private String priKeyPath;

    /**
     *  token过期时间
     */
    private int expire;

    /**
     *  公钥
     */
    private PublicKey publicKey;

    /**
     *  私钥
     */
    private PrivateKey privateKey;

    /**
     *  salt
     */
    private String salt;

    private static final Logger logger = LoggerFactory.getLogger(JwtProperties.class);

    @PostConstruct
    public void init(){
        try {
            File pubKey = new File(pubKeyPath);
            File priKey = new File(priKeyPath);
            if(!pubKey.exists() || !priKey.exists()) {
                //生成公钥和私钥
                RsaUtils.generateKey(pubKeyPath, priKeyPath, secret);
                if(logger.isDebugEnabled()){
                    logger.debug
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值