Springboot中整合Jwt

首先引入jar包

<dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>0.9.1</version>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.8.5</version>
            </dependency>

然后书写工具类用于生成和校验token

@Import(cn.hutool.extra.spring.SpringUtil.class)
public class JwtUtils {
    public static final long Expire = 1000*60*60*24;
    public static final long RExpire = 2;
    public static final TimeUnit RExpiredays = TimeUnit.DAYS;
    //加密的密钥
    private static final String Secret = "wuxing.666";
    //为了区分业务    令牌前缀
    private static final String Token_Pre = "Shop";
    //颁布者:
    private static final String Subject = "wuxing";

    public static Map genToken(LoginUsers loginUsers){
        Assert.notNull(loginUsers,"不能为null");
        Long id = loginUsers.getId();
        HashMap<String, Object> map = new HashMap<>();
        long l = System.currentTimeMillis() + Expire;
        String token = Token_Pre + Jwts.builder().setSubject(Subject)
                .claim("avatar", loginUsers.getAvatar())
                .claim("id", id)
                .claim("ip", loginUsers.getLoginIp())
                .claim("name", loginUsers.getUsername())
                .claim("mail", loginUsers.getEmail())
                .setIssuedAt(new Date())    //设置当前时间
                .setExpiration(new Date(l))
                .signWith(SignatureAlgorithm.HS256, Secret).compact();
        String uuid = IdUtil.fastSimpleUUID();
        RedisTemplate bean = SpringUtil.getBean("redisTemplate");
        bean.opsForValue().set("rtoken:"+uuid, id,RExpire, RExpiredays);
        map.put("token",token);
        map.put("rtoken",uuid);
        map.put("expirtime",l);
        map.put("ip",loginUsers.getLoginIp());
        return map;
    }

    public static Claims checkJwt(String token){
        try {
//            parseClaimsJwt() 方法是解析没有进行签名的token,如果我们的token是已经进行了签名,调用了该方法,就会报出上述错误。
//            签名的token应该使用parseClaimsJws(String jws) 方法
            Claims claims = Jwts.parser().setSigningKey(Secret).parseClaimsJws(token.replace(Token_Pre, "")).getBody();
            return claims;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

上面代码中

Long id = loginUsers.getId();
        HashMap<String, Object> map = new HashMap<>();
        long l = System.currentTimeMillis() + Expire;
        String token = Token_Pre + Jwts.builder().setSubject(Subject)
                .claim("avatar", loginUsers.getAvatar())
                .claim("id", id)
                .claim("ip", loginUsers.getLoginIp())
                .claim("name", loginUsers.getUsername())
                .claim("mail", loginUsers.getEmail())
                .setIssuedAt(new Date(l))    //设置当前时间
                .setExpiration(new Date())
                .signWith(SignatureAlgorithm.HS256, Secret).compact();
        String uuid = IdUtil.fastSimpleUUID();
        RedisTemplate bean = SpringUtil.getBean("redisTemplate");
        bean.opsForValue().set("rtoken:"+uuid, id,RExpire, RExpiredays);
        map.put("token",token);
        map.put("rtoken",uuid);
        map.put("expirtime",l);
        map.put("ip",loginUsers.getLoginIp());

是为了后续实现自动过期刷新
具体逻辑是:
用户登录成功的时候,一次性给他两个Token,分别为AccessToken和RefreshToken
AccessToken有效期较短,比如1天或者5天,用于正常请求
RefreshToken有效期可以设置长一些,例如10天、20天,作为刷新AccessToken的凭证
刷新方案:当AccessToken即将过期的时候,例如提前30分钟,客户端利用RefreshToken请求指定的API获取新的
AccessToken并更新本地存储中的AccessToken
核心逻辑
1、登录成功后,jwt生成AccessToken;UUID生成RefreshToken并存储在服务端redis中,设置过期时间
2、接口返回3个字段AccessToken/RefreshToken/访问令牌过期时间截
3、由于RefreshToken存储在服务端redis中,假如这个RefreshToken也过期,则提示重新登录;
缺点:前端每次请求需要判断token距离过期时间
优点:后端压力小,代码逻辑改动不大

里面绑定ip的话是为了校验ip是否和当前用户ip是否一致,防止滥用token
优点:服务端无需存储相关内容,性能高,假如用户广州登录,泄露了token给杭州的黑客,依旧用不了
缺点:如果用户用使用过程中ip变动频繁,则操作会经常提示重新登录,体验不友好
但为了安全,麻烦是必不可少的。相比除了ip,还有设备号,UA,header头中终端信息,地点等可以采用,进行绑定

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值