如何解决JWT Token劫持被盗安全问题

后端 潘老师 1年前 (2023-11-06) 316 ℃ (0) 扫码查看

如果Token被劫持盗用该怎么办?今天我们来聊一下如何解决JWT Token劫持被盗安全问题,在工作中我们经常要做的一个就是登陆功能,然后获取这个用户的token,后续请求都会带上这个token来验证用户的请求。

Token劫持被盗问题背景

我们经常使用的JWT就是其中一种实现,如下

//生成Token  
public static String generateToken(MapString, Object> payloads) {
        MapString, Object> map = new HashMap(2);
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        Date date = new Date(System.currentTimeMillis() + EXPIRE);
        JWTCreator.Builder jwtBuilder = JWT
                .create()
                .withHeader(map)
                .withExpiresAt(date);
        for (Map.EntryString, Object> entry : payloads.entrySet()) {
            jwtBuilder.withClaim(entry.getKey(), entry.getValue().toString());
        }
        return jwtBuilder.sign(Algorithm.HMAC256(SECRET));
    }

//校验Token
public static MapString, Claim> verifyToken(String token) {
    try{
        JWTVerifier verifier = JWT
                .require(Algorithm.HMAC256(SECRET))
                .build();
        DecodedJWT jwt = verifier.verify(token);
        return jwt.getClaims();
    }catch (Exception e){
        throw new GlobalException(ResponseEnums.TOKEN_VERIFY_FAIL_ERROR);
    }
}

我们会给每一个Token设置一个过期时间,前端拿到这个token以后,在之后的用户每一次请求都会带上这个Token进行校验,如果过期了或者Token格式不对,我们就不让请求通过,直接返回错误信息给前端

        //从请求头中拿到token key : token
String headerToken = request.getHeader(TokenConstant.TOKEN_HEADER);
if (StrUtil.isBlank(headerToken)) {
      throw new GlobalException(ResponseEnums.TOKEN_IS_NULL_ERROR);
}
        
//解析token
MapString, Claim> claimMap = JwtUtil.verifyToken(headerToken);
    return true;
}

这看上去是一件很不错的事情,因为我们解决了用户请求校验的问题,但是这个Token是存储在前端的缓存中的。当我们点击退出登陆的时候,前端也只是把缓存的这个Token给清掉,这样用户后续的请求就没有这个Token,也就会让用户去重新登陆了。这看起来是没有问题的。

但是如果你这个Token还没有过期,这时候你的Token被其他人劫取盗用了,这时候,即使你退出登陆但是这个Token一样是可以通过校验的。所以其他人还是可以拿你这个Token去请求对应的接口。这时候就会有安全问题了。那有没有解决办法呢?

Token劫持被盗解决办法

办法其实是有的。我们可以把这个Token保存到Redis或者数据库中。每次请求的时候,判断一下Redis中有没有这个Token,有就放行,没有就返回错误信息给前端。

当用户点击退出登陆的时候,把Redis的这个Token给删除掉就行了,这样后续即使用人劫取盗用了你这个Token,由于Redis没有,那么第一步返回fasle,就可以直接返回错误信息给前端,不会去执行这个请求

Token劫持被盗思考

既然我们使用了Redis那用JWT的意义在哪呢?我们Redis也可以设置过期时间,还可以给Token续期,很多JWT做不到的事Redis都可以做到。那为什么还要使用JWT呢?这真是一个有趣的问题!


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/10635.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】