wuyouzhuguli/SpringAll · warning · ValidateCodeException
验证码已过期!
Error message
验证码已过期!
What it means
Thrown when ImageCode.isExpire() is true: LocalDateTime.now() is after the code's expireTime. ValidateController creates the code with a 60-second lifetime (expireIn=60). The filter removes the session attribute before throwing, so the code is single-use after expiry.
Source
Thrown at 61.Spring-security-Permission/src/main/java/cc/mrbird/validate/code/ValidateCodeFilter.java:55
return;
}
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
private void validateCode(ServletWebRequest servletWebRequest) throws ServletRequestBindingException {
ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);
String codeInRequest = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), "imageCode");
if (StringUtils.isBlank(codeInRequest)) {
throw new ValidateCodeException("验证码不能为空!");
}
if (codeInSession == null) {
throw new ValidateCodeException("验证码不存在!");
}
if (codeInSession.isExpire()) {
sessionStrategy.removeAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);
throw new ValidateCodeException("验证码已过期!");
}
if (!StringUtils.equalsIgnoreCase(codeInSession.getCode(), codeInRequest)) {
throw new ValidateCodeException("验证码不正确!");
}
sessionStrategy.removeAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);
}
}
View on GitHub (pinned to 614d2578d9)
Solutions
- Refresh the captcha image (GET /code/image) and resubmit a fresh code within 60 seconds.
- Increase expireIn in ValidateController.createImageCode (and the matching SmsCode lifetime) if users need more time.
- On the frontend, auto-refresh the captcha image when the user focuses the login form or after a failure.
Example fix
// before (ValidateController.createImageCode) // int expireIn = 60; // 验证码有效时间 60s // after int expireIn = 300; // extend to 5 minutes
Defensive patterns
Strategy: retry
Validate before calling
// Track when the captcha was fetched; refresh if older than 50s (TTL is 60s).
let captchaFetchedAt = 0;
async function ensureFreshCaptcha() {
if (Date.now() - captchaFetchedAt > 50_000) { await refreshCaptcha(); }
} Try / catch
try { await login(); }
catch (e) {
if (/已过期/.test(e.message)) { await refreshCaptcha(); /* user re-enters */ }
else handleError(e);
} Prevention
- Show a countdown to the user based on the 60s TTL.
- Auto-refresh the image when it is about to expire.
- Raise expireIn in ValidateController if users need more time.
When it happens
Trigger: More than 60 seconds elapsed between GET /code/image and the login POST; the user lingered on the form or typed slowly; client clock vs the generated code's plusSeconds(60) window was exceeded.
Common situations: Default 60s expiry is too short for slow users; user refreshed only the form (not the image) and submitted a stale code; debugging paused between fetch and submit.
Related errors
AI-assisted analysis of wuyouzhuguli/SpringAll@614d2578d9 (2026-08-14).
Data as JSON: /api/errors/3e673ca9bd9df465.
Report an issue: GitHub.