Jwt退出登陆

虽然我们使用JWT已经很方便了,但是有一个很严重的问题就是,我们没办法像Session那样去踢用户下线,什么意思呢?我们之前可以使用退出登录接口直接退出,用户Session中的验证信息也会被销毁,但是现在是无状态的,用户来管理Token令牌,服务端只认Token是否合法,那这个时候该怎么让用户正确退出登录呢?

首先我们从最简单的方案开始,我们可以直接让客户端删除自己的JWT令牌,这样不就相当于退出登录了吗,这样甚至不需要请求服务器,直接就退了

这样虽然是最简单粗暴的,但是存在一个问题,用户可以自行保存这个Token拿来使用。虽然客户端已经删除掉了,但是这个令牌仍然是可用的,如果用户私自保存过,那么依然可以正常使用这个令牌,这显然是有问题的。

目前有两种比较好的方案:

  • 黑名单方案:所有黑名单中的JWT将不可使用。

  • 白名单方案:不在白名单中的JWT将不可使用。

这里我们以黑名单机制为例,让用户退出登录之后,无法再次使用之前的JWT进行操作,首先我们需要给JWT额外添加一个用于判断的唯一标识符,这里就用UUID好了

我们使用redis实现黑名单

依赖导入:

```Plain Text org.springframework.boot spring-boot-starter-data-redis

在jwt工具类中添加让令牌失效的方法:

Java public boolean invalidateJwt(String headerToken){ String token=this.convertToken(headerToken); if (token==null){ return false; } Algorithm algorithm=Algorithm.HMAC256(key); JWTVerifier jwtVerifier = JWT.require(algorithm).build(); try {

    }
}
可以将令牌直接存到redis里面,更简单的方法是给令牌加个id,查找时直接通过id比较,因此在创建令牌是增加jwtid:

Java 在create方法中添加 .withJWTId(UUID.randomUUID().toString())

在try中获取令牌对应的id并进行检验,确定是否存在和是否过期:

Java try { DecodedJWT jwt=jwtVerifier.verify(token); String id=jwt.getId(); return deleteToken(id,jwt.getExpiresAt()); }catch (JWTVerificationException e){ return false; }

对应删除和检验方法的实现:

Java private boolean deleteToken(String uuid,Date time){ if (isInvalidToken(uuid)){ return false; } Date now=new Date();; long expire=Math.max(time.getTime()-now.getTime(),0); template.opsForValue().set(Const.JWTBLACKLIST+uuid,"",expire, TimeUnit.MILLISECONDS); return true; }

private boolean isInvalidToken(String uuid  ){
    return  Boolean.TRUE.equals(template.hasKey(Const.JWT_BLACK_LIST+uuid));
}
创建const类保存jwt黑名单

Java public class Const { public static final String JWTBLACKLIST="jwt:blacklist:"; }

编写logout方法:

Java public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

    response.setContentType("application/json;charset=utf-8");
    PrintWriter writer = response.getWriter();
    String authorization=request.getHeader("Authorization");
    if (utils.invalidateJwt(authorization)){
        writer.write(RestBean.success().asJsonString());
    }
    else {
        writer.write(RestBean.failure(400,"token失效").asJsonString());
    }

    System.out.println("logoutsuccess");
}

}

```

在JWT中,所有颁发的token都可以再次使用,通过在服务器设立黑名单机制,才可以真正的实现用户的退出登陆。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

glassy_sky6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值