jeecgboot/JeecgBoot · error · JeecgBoot401Exception

token不能为空!

Error message

token不能为空!

What it means

Thrown by TokenUtils.verifyToken when the X-Access-Token header (or token parameter) extracted from the request is null or blank. It is the first guard in the JWT verification chain and returns HTTP 401 via JeecgBoot401Exception. It fires before any signature or Redis lookup, so it is purely a presence check.

Source

Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java:103

        }
        return lowAppId;
    }

    /**
     * 验证Token
     */
    public static boolean verifyToken(HttpServletRequest request, CommonAPI commonApi, RedisUtil redisUtil) {
        log.debug(" -- url --" + request.getRequestURL());
        String token = getTokenByRequest(request);
        return TokenUtils.verifyToken(token, commonApi, redisUtil);
    }

    /**
     * 验证Token
     */
    public static boolean verifyToken(String token, CommonAPI commonApi, RedisUtil redisUtil) {
        if (StringUtils.isBlank(token)) {
            throw new JeecgBoot401Exception("token不能为空!");
        }

        // 解密获得username,用于和数据库进行对比
        String username = JwtUtil.getUsername(token);
        if (username == null) {
            throw new JeecgBoot401Exception("token非法无效!");
        }

        // 查询用户信息
        LoginUser user = TokenUtils.getLoginUser(username, commonApi, redisUtil);
        //LoginUser user = commonApi.getUserByName(username);
        if (user == null) {
            throw new JeecgBoot401Exception("用户不存在!");
        }
        // 判断用户状态
        if (user.getStatus() != 1) {
            throw new JeecgBoot401Exception("账号已被锁定,请联系管理员!");
        }

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Attach the JWT to every authenticated request: header 'X-Access-Token: <token>' (JeecgBoot convention) or the configured token header.
  2. After login, persist the returned token and have the axios/uni request interceptor read it from storage on each call.
  3. Handle a 401 with the message 'token不能为空!' by redirecting the user to the login page rather than retrying.
  4. If behind a gateway, verify it forwards X-Access-Token and Authorization headers unchanged.

Example fix

// before (frontend interceptor missing header)
axios.get('/sys/user/list')

// after
axios.interceptors.request.use(cfg => {
  const token = Vue.ls.get('Access-Token');
  if (token) cfg.headers['X-Access-Token'] = token;
  return cfg;
});
Defensive patterns

Strategy: validation

Validate before calling

String token = request.getHeader("X-Access-Token");
if (StringUtils.isBlank(token)) {
    response.setStatus(401);
    return;
}

Type guard

public static boolean hasToken(HttpServletRequest r){
    String t = r.getHeader("X-Access-Token");
    return t != null && !t.trim().isEmpty() && !"null".equalsIgnoreCase(t);
}

Try / catch

try { TokenUtils.verifyToken(request, commonApi, redisUtil); }
catch (JeecgBoot401Exception e) { response.sendError(401, e.getMessage()); }

Prevention

When it happens

Trigger: Any authenticated request (controller behind the shiro/jwt filter) sent without the token header, with an empty Authorization value, or where a gateway/proxy stripped the header. Also occurs during dev when the frontend stores the token in localStorage but the interceptor does not attach it.

Common situations: User session expired and the token was cleared client-side but the page kept making AJAX calls; misconfigured nginx/cors stripping X-Access-Token; a script/Postman call that forgot the header; a logged-out tab still open.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/5bd82e27b5a67911. Report an issue: GitHub.