wuyouzhuguli/SpringAll · warning · Exception

验证码已过期!

Error message

验证码已过期!

What it means

A plain java.lang.Exception '验证码已过期!' (verification code expired) is thrown by SmsCodeFilter.validateCode when redisCodeService.get(...) returns null for the given mobile. The SMS code is stored in Redis with a TTL keyed by mobile number; a null means no code exists under that key. This gate runs before the SMS authentication provider.

Source

Thrown at 65.Spring-Security-OAuth2-Config/src/main/java/cc/mrbird/security/validate/smscode/SmsCodeFilter.java:52

            } catch (Exception e) {
                authenticationFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, new AuthenticationServiceException(e.getMessage()));
                return;
            }
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }

    private void validateCode(ServletWebRequest servletWebRequest) throws Exception {
        String smsCodeInRequest = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), "smsCode");
        String mobileInRequest = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), "mobile");

        String codeInRedis = redisCodeService.get(servletWebRequest, mobileInRequest);

        if (StringUtils.isBlank(smsCodeInRequest)) {
            throw new Exception("验证码不能为空!");
        }
        if (codeInRedis == null) {
            throw new Exception("验证码已过期!");
        }
        if (!StringUtils.equalsIgnoreCase(codeInRedis, smsCodeInRequest)) {
            throw new Exception("验证码不正确!");
        }
        redisCodeService.remove(servletWebRequest, mobileInRequest);

    }
}

View on GitHub (pinned to 614d2578d9)

Solutions

  1. Request a fresh SMS code (re-trigger the send-code endpoint) and submit login within the configured TTL window.
  2. Verify redisCodeService uses an identical key (same mobile normalization and prefix) for both set (on send) and get (on validate), and that the TTL on set is non-zero.
  3. Confirm validateCode's remove() is only called after a successful match, so legitimate first attempts are not prematurely invalidated.
  4. Check Redis connectivity and that keys survive across requests (no flush, correct DB index, persistent rather than in-memory config in tests).
  5. Make the code's expiry window explicit to the user (countdown UI) so submissions land inside the TTL.

Example fix

// before
if (codeInRedis == null) {
    throw new Exception("验证码已过期!");
}

// after — typed exception + distinguish never-issued vs expired
if (codeInRedis == null) {
    throw new ValidateCodeException("验证码已过期或未发送,请重新获取");
}
Defensive patterns

Strategy: validation

Validate before calling

// Check existence in Redis before delegating to the throwing filter
boolean codeAlive = redisCodeService.get(new ServletWebRequest(request), mobile) != null;
if (!codeAlive) {
    return "验证码已失效,请重新获取";
}

Type guard

private boolean codeStillValid(ServletWebRequest req, String mobile) {
    return redisCodeService.get(req, mobile) != null;
}

Try / catch

try {
    filterChain.doFilter(request, response);
} catch (Exception e) {
    if ("验证码已过期!".equals(e.getMessage())) {
        response.setStatus(400);
        response.getWriter().write("验证码已过期,请重新获取");
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: The SMS code's Redis TTL elapsed before login was attempted; the code was already consumed by a successful prior validate (validateCode calls redisCodeService.remove after a match, so resubmission hits null); the code was never generated/sent for that mobile; or Redis was flushed/restarted losing the key.

Common situations: User waited longer than the configured code validity window (often 60–300s) before submitting; double-submit of the login form after a first success (remove-on-success deletes the key); the SMS-send endpoint and the validate endpoint key the code differently (different mobile normalization or key prefix); or the Redis connection/serialization changed so get returns null for a key that was written by a prior deploy.

Related errors


AI-assisted analysis of wuyouzhuguli/SpringAll@614d2578d9 (2026-08-14). Data as JSON: /api/errors/b1ecf741d713980f. Report an issue: GitHub.