elunez/eladmin · error · BadRequestException
验证码不存在或已过期
Error message
验证码不存在或已过期
What it means
AuthController.login looks up the captcha in Redis by the client-supplied uuid (redisUtils.get(uuid)), deletes it immediately (one-time use), and if the stored code is blank throws '验证码不存在或已过期'. The captcha was either never stored, already consumed, or its TTL expired.
Source
Thrown at eladmin-system/src/main/java/me/zhengjie/modules/security/rest/AuthController.java:88
private final OnlineUserService onlineUserService;
private final TokenProvider tokenProvider;
private final LoginProperties loginProperties;
private final CaptchaConfig captchaConfig;
private final PasswordEncoder passwordEncoder;
private final UserDetailsServiceImpl userDetailsService;
@Log("用户登录")
@ApiOperation("登录授权")
@AnonymousPostMapping(value = "/login")
public ResponseEntity<Object> login(@Validated @RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception {
// 密码解密
String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, authUser.getPassword());
// 查询验证码
String code = redisUtils.get(authUser.getUuid(), String.class);
// 清除验证码
redisUtils.del(authUser.getUuid());
if (StringUtils.isBlank(code)) {
throw new BadRequestException("验证码不存在或已过期");
}
if (StringUtils.isBlank(authUser.getCode()) || !authUser.getCode().equalsIgnoreCase(code)) {
throw new BadRequestException("验证码错误");
}
// 获取用户信息
JwtUserDto jwtUser = userDetailsService.loadUserByUsername(authUser.getUsername());
// 验证用户密码
if (!passwordEncoder.matches(password, jwtUser.getPassword())) {
throw new BadRequestException("登录密码错误");
}
Authentication authentication = new UsernamePasswordAuthenticationToken(jwtUser, null, jwtUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
// 生成令牌
String token = tokenProvider.createToken(jwtUser);
// 返回 token 与 用户信息
Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
put("token", properties.getTokenStartWith() + token);
put("user", jwtUser);View on GitHub (pinned to 55fbf70595)
Solutions
- Refresh the captcha image (fetches a new uuid+code) and log in promptly within the TTL.
- Prevent double submission in the frontend (disable the button while the request is in flight).
- Verify Redis connectivity and that the login code TTL (login.code.expiration, typically 2 minutes) suits your users.
- Ensure the Redis database/host config matches between environments if codes seem to vanish.
Example fix
// frontend pseudo-code // before: reuse old uuid after failed attempt login(oldUuid, code); // after: always fetch a fresh captcha after any login failure await getCode(); // sets new uuid + image login(newUuid, inputCode);
Defensive patterns
Strategy: validation
Validate before calling
// frontend: ensure a live captcha accompanies every login attempt
if (!this.uuid || !this.code) { await this.getCode(); throw new Error('请先获取并填写验证码'); }
// and always refresh after any failed attempt:
catch (e) { await this.getCode(); throw e; } Try / catch
try { await login(payload); } catch (e) { if (e.message.includes('验证码不存在或已过期')) { await refreshCaptcha(); focusCodeInput(); return; } throw e; } Prevention
- Refresh the captcha after EVERY login failure — codes are single-use and deleted on read.
- Disable the submit button during the request to prevent double submits that burn the code.
- Confirm Redis persistence and a sane login.code.expiration (>= typical user fill time).
When it happens
Trigger: POST /auth/login with a uuid for which Redis has no entry: submitting after the captcha expired (default TTL is short), double-submitting the login form (first attempt consumed the code), Redis flushed/restarted without persistence, or the frontend sending a stale/absent uuid.
Common situations: User leaves the login page open past the captcha expiry then submits; double-click of the login button; Redis restart with no RDB/AOF so all captcha keys vanished; frontend bug reusing an old uuid; wrong Redis database index in config (code stored in another db than the one read).
Related errors
AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14).
Data as JSON: /api/errors/3b595cbfcb3ab3f2.
Report an issue: GitHub.