code: public Boolean validate(String token, JwtUserDetail userDetails) {
          if (StringUtils.isBlank(token) || userDetails == null) {
              return false;
          }
          String key = jwtProperties.getPrefix() + Md5Utils.digestMD5(token);
          JwtToken jwtToken = cacheService.get(key);
          // 判断是否在黑名单中
          if (jwtToken != null) {
              //销毁状态
              if (JwtToken.Operation.destroy.getValue() == jwtToken.getType()) {
                  return false;
              }
  
              Long refreshTime = jwtToken.getRefreshTime();
              if (refreshTime != null && jwtToken.getType() == JwtToken.Operation.refresh.getValue()) {
                  // 刷新token二分钟内可以使用
                  return Instant.now().toEpochMilli() - refreshTime < 1000 * 60 * 2;
              }
          }
          final Instant created = jwtBuilder.getCreatedTimeFromToken(token);
          final String loginName = jwtBuilder.getLoginNameFromToken(token);
          LocalDateTime modifyPasswordTime = userDetails.getModifyPasswordTime();
          if (Objects.isNull(modifyPasswordTime)) {
              return Objects.equals(loginName, userDetails.getUsername())
                      && !jwtBuilder.isExpired(token);
          }
          return Objects.equals(loginName, userDetails.getUsername())
                  && !jwtBuilder.isExpired(token) && validate(created, modifyPasswordTime);
      }
docs: 校验token是否合法
  
  @param token       token的值
  @param userDetails 用户信息
  @return true:合法，false：非法