jwt token定时刷新

一、token定时刷新的意义
因为登录后获得的token是有时间限制的,也即是有效期,刷新token一是可以延续token二是可以保证安全,即使token被人截获 刷新token后也还是很安全的

二、大致实现步骤
在前端登录后的主页 的公共模块或公共组件里面设置一个Interval,也即是每隔一定周期 去请求后台,通过先前的token得到一个新token,然后前端获取

三、代码实现:
1.后台:

/**
 * @Description: 刷新token
 * @Author: tony
 * @Date: 2020/1/22 15:40
 **/
@RestController
@RequestMapping("/")
public class TokenController {
    private final Logger logger= LoggerFactory.getLogger(TokenController.class);

    /**
     * 刷新用户token
     * @param request
     * @return
     */
    @GetMapping(value = "/refreshToken")
    public R refreshToken(HttpServletRequest request){
        //这里生成claims,下面就可以根据claims得到id和用户名  从而索取到新的token
        Claims claims = JwtUtils.validateJWT(request.getHeader("token")).getClaims();

        String newToken = JwtUtils.createJWT(claims.getId(), claims.getSubject(), SystemConstant.JWT_TTL);
        R r = new R();
        r.put("token",newToken);
        logger.info("新token: "+newToken);
        return r;
    }
}

2.Jwt工具类:

/**
 * jwt加密和解密的工具类
 */
public class JwtUtils {

    /** 比如用户输入用户名和密码 若登录合法就生成jwt的一个token 发送给前端 前端存储到localStorage
     *  然后用户每次发起请求都从本地获取 携带着一个token送至后台 去验证  从而完成身份的验证
     * 签发JWT
     * @param id 一般是用户id
     * @param subject 一般是用户名 可以是JSON数据 尽可能少
     * @param ttlMillis  有效期 这里是1小时
     * @return
     */
    public static String createJWT(String id, String subject, long ttlMillis) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey secretKey = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setId(id)
                .setSubject(subject)   // 主题
                .setIssuer("Java1234")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey); // 签名算法以及密匙
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date expDate = new Date(expMillis);
            builder.setExpiration(expDate); // 过期时间
        }
        return builder.compact();
    }

    /**
     * 验证JWT  需要把jwt的token传过来
     * @param jwtStr
     * @return
     */
    public static CheckResult validateJWT(String jwtStr) {
        CheckResult checkResult = new CheckResult();
        Claims claims = null;
        try {
            claims = parseJWT(jwtStr);  // 里面包含有id,subject(用户名),有效期等信息
            checkResult.setSuccess(true);  //封装进checkResult
            checkResult.setClaims(claims);
        } catch (ExpiredJwtException e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_EXPIRE);
            checkResult.setSuccess(false);
        } catch (SignatureException e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        } catch (Exception e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        }
        return checkResult;
    }

    /**
     * 生成加密Key
     * 解密时也要用到 因为在刷新token时要通过原来生成的token解密获取用户id 和用户名(subject) 重新生成token
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decode(SystemConstant.JWT_SECERT);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }


    /**
     * 解析JWT字符串
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }

    public static void main(String[] args) throws InterruptedException {
         // 后端生成token
        String sc=createJWT("1","jack",SystemConstant.JWT_TTL);
        System.out.println(sc);

        // 后端验证token
        CheckResult checkResult = validateJWT(sc);
        System.out.println(checkResult.isSuccess()); //true为验证成功
        System.out.println(checkResult.getErrCode());// code为0  表示无异常
        Claims claims=checkResult.getClaims();
        System.out.println(claims);
        System.out.println(claims.getId());
        System.out.println(claims.getSubject());

        // 刷新token 重新生成token 和之前的token不同
        //刷新token时要通过原来生成的token解密获取用户id 和用户名(subject) 重新生成token
        Claims claims2=validateJWT(sc).getClaims();
        String sc2=createJWT(claims2.getId(),claims2.getSubject(),SystemConstant.JWT_TTL);
        System.out.println(sc2);
    }

}

3.前端:

export default {
    name: "PhoneBook",
    methods: {
      refreshToken(){
        let token = window.localStorage.getItem("token");
        axios.defaults.headers.common['token'] = token
        let url = getServerUrl("refreshToken");
        axios.get(url)
          .then(response=>{
            console.log("token刷新: "+response.data.token)
            window.localStorage.setItem("token",response.data.token);
          }).catch(error=>{
            console.log(error)
        })
      },
      getPhoneBooks() {
        let token = localStorage.getItem("token");
        alert(token)
        axios.defaults.headers.common['token']=token;

        let url  = getServerUrl("phoneBook/loadAll");
        axios.get(url)
          .then(response=>{
            console.log(response)
          }).catch(error=>{
            console.log(error)
        })
      }
    },
    mounted() {
      setInterval(this.refreshToken,1000*60*10);//每10分钟刷新一次token
      this.getPhoneBooks(); //加载所有电话簿信息
    }
  }
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值