使用JWT你应该要注意Token劫持安全问题-Java专区论坛-技术-SpringForAll社区

使用JWT你应该要注意Token劫持安全问题

大家好,我是小趴菜,在工作中我们经常要做的一个就是登陆功能,然后获取这个用户的token,后续请求都会带上这个token来验证用户的请求。

问题背景

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

//生成Token  
public static String generateToken(Map<String, Object> payloads) {
        Map<String, 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.Entry<String, Object> entry : payloads.entrySet()) {
            jwtBuilder.withClaim(entry.getKey(), entry.getValue().toString());
        }
        return jwtBuilder.sign(Algorithm.HMAC256(SECRET));
    }

//校验Token
public static Map<String, 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
        Map<String, Claim> claimMap = JwtUtil.verifyToken(headerToken);
        return true;
    }

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

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

解决办法

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

d2b5ca33bd20231107155006

 

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

思考

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

作者:我是小趴菜,链接:https://juejin.cn/post/7298132141636403210

请登录后发表评论

    没有回复内容