欢迎访问本站,持续更新中…

Java,Spring Boot JWT加密、解密

介绍

JSON Web 令牌 (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,用于作为 JSON 对象在各方之间安全地传输信息。由于此信息已进行数字签名,因此可以对其进行验证和信任。可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对对 JWT 进行签名。

1、引入包


      <dependency>
          <groupId>com.auth0</groupId>
          <artifactId>java-jwt</artifactId>
          <version>3.8.1</version>
      </dependency>
      <dependency>
          <groupId>io.jsonwebtoken</groupId>
          <artifactId>jjwt</artifactId>
          <version>3.8.1</version>
      </dependency>

2、签名算法

  /**
   * 签名算法
   */
  private static final SignatureAlgorithm signatureAlgorithm;

3、静态实例化值

  /**
   * 静态默认值
   */
  static {
    signatureAlgorithm = SignatureAlgorithm.HS512;
  }

4、加密

  /**
   * 前三个参数为自己用户token的一些信息比如id,权限,名称等。不要将隐私信息放入(大家都可以获取到)
   *
   * @param map            参数
   * @param base64Security 密钥
   * @return 返回结果
   */
  public static String createJwt(Map<String, Object> map, String base64Security) {
    //添加构成JWT的参数
    JwtBuilder builder = builderJwt(map, base64Security);
    //生成JWT token
    return builder.compact();
  }

  /**
   * 前三个参数为自己用户token的一些信息比如id,权限,名称等。不要将隐私信息放入(大家都可以获取到)
   *
   * @param map            参数
   * @param base64Security 密钥
   * @param expiration     过期时间
   * @return 返回结果
   */
  public static String createJwt(Map<String, Object> map, String base64Security, long expiration) {
    //添加构成JWT的参数
    JwtBuilder builder = builderJwt(map, base64Security);
    builder.setExpiration(new Date(expiration));
    //生成JWT
    return builder.compact();
  }

  /**
   * 构建 jwt
   *
   * @param map            值
   * @param base64Security 密钥
   * @return 返回结果
   */
  private static JwtBuilder builderJwt(Map<String, Object> map, String base64Security) {
    return Jwts.builder().setHeaderParam("typ", "JWT")
        .setClaims(map)
        //估计是第三段密钥
        .signWith(signatureAlgorithm, base64Security.getBytes());
  }

5、解密

  /**
   * 解密
   *
   * @param jsonWebToken   token
   * @param base64Security 密钥
   * @return 返回结果
   */
  public static Claims parseJwt(String jsonWebToken, String base64Security) {
    try {
      Claims claims = Jwts.parser()
          .setSigningKey(base64Security.getBytes())
          .parseClaimsJws(jsonWebToken).getBody();
      return claims;
    } catch (Exception ex) {
      ex.printStackTrace();
      return null;
    }
  }

6、检查token

  /**
   * 检查token
   *
   * @param jwtToken       token
   * @param base64Security base64安全性
   * @param userAgent      用户代理
   * @return 返回 redis token
   * @throws Exception 异常信息
   */
  public static String checkToken(String jwtToken, String base64Security, String userAgent) throws GlobalException {
    String token;
    try {
      Claims claims = parseJwt(jwtToken, base64Security);
      long effective = IntegerConsts.TWENTY_FOUR * IntegerConsts.SIXTY * IntegerConsts.SIXTY;
      Long time = ConvertUtils.convertLong(claims.get(BusinessConsts.TIME));
      if (time <= IntegerConsts.ZERO) {
        time = ConvertUtils.convertLong(claims.get(BusinessConsts.EXP));
      }

      // 验证 token 是否过期
      LocalDateTime localDateTime = LocalDateUtils.timestampToLocalDateTime(time)
          .plusSeconds(effective);
      if (LocalDateUtils.greater(localDateTime, LocalDateTime.now())) {
        throw new GlobalException("token 过期!");
      }

      // 验证 token 签名
      Object loginName = claims.get(BusinessConsts.USER_NAME);
      if (StringUtils.isNullAndSpaceOrEmpty(loginName)) {
        loginName = claims.get(BusinessConsts.LOGIN_NAME);
      }
      StringBuilder builder = new StringBuilder();
      builder.append(String.format("loginName=%s&effective=%s&time=%s&userAgent=%s", loginName, effective, time, userAgent));
      token = String.valueOf(claims.get(BusinessConsts.HEADER_TOKEN));
      String tokenPassword = Md5Utils.getMd5(builder.toString());
      if (!tokenPassword.equals(token)) {
        throw new GlobalException("token 签名验证失败!");
      }
    } catch (Exception ex) {
      String message = "token 验证失败!";
      if (ex instanceof GlobalException) {
        message = ex.getMessage();
      }
      throw new GlobalException(message);
    }

    // 返回结果
    return token;
  }

7、测试

  public static void main(String[] args) {
    // 生成 JWT token
    Map<String, Object> map = new HashMap<>(IntegerConsts.FOUR);
    map.put(BusinessConsts.LOGIN_NAME, "username");
    long time = System.currentTimeMillis() / IntegerConsts.ONE_THOUSAND;
    map.put(BusinessConsts.TIME, time);
    map.put(BusinessConsts.USER_NAME, "username");
    map.put(BusinessConsts.USER_TYPE, "userType");
    map.put(BusinessConsts.DISPLAY_NAME, "displayName");
    // 暂不需要该参数
    String userAgent = StringUtils.Empty;
    StringBuilder builder = new StringBuilder();
    /**
     * 加密 token 参数
     */
    long EFFECTIVE = IntegerConsts.TWENTY_FOUR * IntegerConsts.SIXTY * IntegerConsts.SIXTY;
    String TOKEN_ENCRYPTION = "loginName=%s&effective=%s&time=%s&userAgent=%s";
    builder.append(String.format(TOKEN_ENCRYPTION,
        "username", EFFECTIVE, time, userAgent));
    String tokenValue = Md5Utils.getMd5(builder.toString());
    map.put(BusinessConsts.HEADER_TOKEN, tokenValue);

    //密钥
    String key = "cdkj-framework-jwt";
    String token = JwtUtils.createJwt(map, key, System.currentTimeMillis() + 10000);

    try {
      JwtUtils.checkToken(token, key, "");
    } catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println("JWT加密的结果:" + token);
    System.out.println("JWT解密的结果:" + parseJwt(token, key));
  }

测试结果