token的使用

基于springboot-gradle创建项目,不懂得小伙伴可以前往我的博客: springboot使用gradle

token官网: https://jwt.io/

token概念

	 token 令牌:
    JWT: JSON Web Token 是一种标准
    java-jwt 框架 是java实现的JWT标准的一个框架

    JWT标准: token由三部分组成,每部分之间使用'.'分开
    第一部分: 头(header)
        里面保存了该token的加密方式
    第二部分: 负载(payload)
        里面保存了用户信息/token的信息(id/过期时间等等)
    第三部分: 校验信息

    第一部分和第二部分是JSON格式的数据使用Base64编码后的信息
    注意: 该部分的信息是明文,不能存储敏感数据

springboot-gradle-token

springboot-gradle-token

springboot-gradle-token

springboot-gradle-token

springboot-gradle-token

springboot-gradle-token

具体代码如下:

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.lanou3g.tokendemo111.utils.JwtUtils;
import org.junit.Test;

import java.util.Date;

public class TokenTest {

    // 自定义**,可以自己随便写,越复杂越好
    public static final String SECRET_KEY = "53g2jkj2be215k1b1";

    @Test
    public void createToken() {
        // 创建token
        String token = JWT.create()
                // 在负载中添加自定义的数据
                .withClaim("userId", 1001)
                .withClaim("username", "admin")
                // 发布时间,也就是生成时间,可以稍微记录一下上次的登录时间
                .withIssuedAt(new Date())
                // 设置该token的过期时间
                // 10秒钟后该token过期
                .withExpiresAt(new Date(System.currentTimeMillis() + 100000))
                // sign要在最后调用,使用Algorithm选择加密方式,常用HMAC256
                .sign(Algorithm.HMAC256(SECRET_KEY));
        System.out.println(token);
        // 生成后的token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NDEwNDEzNDksInVzZXJJZCI6MTAwMSwiaWF0IjoxNTQxMDQxMzM5LCJ1c2VybmFtZSI6Imt0bG42NjYifQ.tU_kElllOPZq4A67VEJCODlwD3OFi6ntC4V8ARO60Q0
    }

    @Test
    public void require() {
        // 根据校验规则HMAC256生成校验对象
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET_KEY)).build();
        try {
            // 校验前端发送过来的token是否合法
            // 如果合法会返回一个解码后的jwt对象
            // 如果不合法,会抛出xxx异常
            // verify参数填写上面方法生成的token
            DecodedJWT jwt = verifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NDEwNDMzNzcsInVzZXJJZCI6MTAwMSwiaWF0IjoxNTQxMDQzMjc3LCJ1c2VybmFtZSI6Imt0bG42NjYifQ.fCFxLol9V_a0DBdxi63jgtC2_6s2C81l9CpXd0oN85s");
            System.out.println(jwt.getHeader());
            System.out.println(jwt.getPayload());
        } catch (TokenExpiredException e) {
            System.out.println("Token已经过期");
        } catch (SignatureVerificationException e) {
            System.out.println("Token不合法");
        } catch (Exception e) {
            System.out.println("认证失败");
        }
    }

}


springboot-gradle-token

springboot-gradle-token

springboot-gradle-token

springboot-gradle-token

下面我们来模拟一下如果token到期时间高于80%,就返回给他一个新的token,代码如下:

新建一个工具类:

springboot-gradle-token


import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Date;

public class JwtUtils {

    /**
     * 默认过期时间30分钟
     *
     * @param userId 用户ID
     * @return token
     */
    public static String newToken(Long userId) {
        // 为一个用户设置token并设置默认到期时间
        return newToken(userId, Constants.DEFAULT_EXPIRED_SECONDS);
    }

    /**
     * @param userId         用户ID
     * @param expiredSeconds 过期时长
     * @return token
     */
    public static String newToken(Long userId, long expiredSeconds) {
        return JWT.create()
                .withClaim("userId", userId)
                // 发布时间
                .withIssuedAt(new Date())
                // 到期时间
                .withExpiresAt(new Date(System.currentTimeMillis() + expiredSeconds * 1000))
                // 选择加密方式
                .sign(Algorithm.HMAC256(Constants.SECRET_KEY));
    }

    /**
     * 校验token是否合法
     *
     * @param token 需要校验的token
     * @return 是否合法
     */
    public static boolean checkToken(String token) {
        // 根据校验规则HMAC256生成校验对象
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(Constants.SECRET_KEY)).build();
        try {
            // 校验token是否合法
            verifier.verify(token);
            return true;
        } catch (JWTVerificationException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 刷新token
     *
     * @param token 原token
     * @return 新token
     */
    public static String refreshToken(String token) {
        // 进行Base64解码
        DecodedJWT jwt = JWT.decode(token);
        // 获得解码后token里的负载中的用户ID
        Long userId = jwt.getClaim("userId").asLong();
        // 调用上面的创建token的方法创建新的token
        return newToken(userId);
    }

    /**
     * token到期时间高于80%,就返回给他一个新的token,并做校验
     * @param token
     * @return
     */
    public static String autoRequire(String token) {
        // 校验token
        boolean check = checkToken(token);
        if (check) {
            // 解码
            DecodedJWT jwt = JWT.decode(token);
            // 计算时间是否超过80%
            long current = System.currentTimeMillis() / 1000;
            // 获取开始时间
            Long start = jwt.getClaim("iat").asLong();
            // 获取结束时间
            Long end = jwt.getClaim("exp").asLong();
            if ((current - start) * 1.0 / (end - start) > 0.8) {
                // 时间超过80%返回新的token
                return refreshToken(token);
            } else {
                // 返回原来的token
                return token;
            }
        } else {
            throw new JWTVerificationException("token不合法");
        }
    }

}


回到之前的测试类:

springboot-gradle-token

springboot-gradle-token

附加: gethub 源码地址: https://github.com/JianJieMing/JianJieMing_JAVA/tree/master/token-demo-11-1

源码上有个基于token模拟用户登录的demo,token到期无法访问指定页面(附加拦截器,异常处理)

springboot-gradle-token

相关文章:

  • 2021-09-17
  • 2021-04-07
  • 2022-12-23
  • 2022-12-23
  • 2021-12-17
  • 2021-10-15
  • 2021-10-16
  • 2021-04-05
猜你喜欢
  • 2022-12-23
  • 2021-05-12
  • 2021-12-13
  • 2021-04-21
  • 2021-06-10
  • 2021-07-05
  • 2021-07-12
相关资源
相似解决方案