{"record":{"id":"41b3877c68b0eee0","repo":"wuyouzhuguli/SpringAll","slug":"error-41b387","errorCode":null,"errorMessage":"验证码已过期！","messagePattern":"验证码已过期！","errorType":"validation","errorClass":"ValidateCodeException","httpStatus":null,"severity":"warning","filePath":"59.Spring-Security-SessionManager/src/main/java/cc/mrbird/validate/code/ValidateCodeFilter.java","lineNumber":55,"sourceCode":"                return;\n            }\n        }\n        filterChain.doFilter(httpServletRequest, httpServletResponse);\n    }\n\n    private void validateCode(ServletWebRequest servletWebRequest) throws ServletRequestBindingException {\n        ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);\n        String codeInRequest = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), \"imageCode\");\n\n        if (StringUtils.isBlank(codeInRequest)) {\n            throw new ValidateCodeException(\"验证码不能为空！\");\n        }\n        if (codeInSession == null) {\n            throw new ValidateCodeException(\"验证码不存在！\");\n        }\n        if (codeInSession.isExpire()) {\n            sessionStrategy.removeAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);\n            throw new ValidateCodeException(\"验证码已过期！\");\n        }\n        if (!StringUtils.equalsIgnoreCase(codeInSession.getCode(), codeInRequest)) {\n            throw new ValidateCodeException(\"验证码不正确！\");\n        }\n        sessionStrategy.removeAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);\n\n    }\n\n}\n","sourceCodeStart":37,"sourceCodeEnd":65,"githubUrl":"https://github.com/wuyouzhuguli/SpringAll/blob/614d2578d9495acf53cc02f2dee9c6131cc5e51a/59.Spring-Security-SessionManager/src/main/java/cc/mrbird/validate/code/ValidateCodeFilter.java#L37-L65","documentation":"Thrown by ValidateCodeFilter.validateCode when the session ImageCode exists but its isExpire() returns true. The captcha (default 60s, ValidateController.createImageCode) outlived its validity window. Before throwing, the filter removes the expired code from session so it cannot be reused.","triggerScenarios":"More than the configured expireIn (60s) elapsed between GET /code/image and the POST /login; the user left the page idle then submitted the stale captcha.","commonSituations":"Long user think-time on the login form; short captcha TTL; clock/session delays; slow typing that exceeds 60 seconds.","solutions":["Submit the form within the 60-second validity window configured in createImageCode.","Auto-refresh the captcha image (re-call GET /code/image) when it is about to expire.","Increase the expireIn value in ValidateController.createImageCode if users legitimately need more time.","On the client, show a countdown and force a re-fetch of the image when it hits zero."],"exampleFix":"// before\nint expireIn = 60; // 验证码有效时间 60s\n\n// after\nint expireIn = 180; // allow more time","handlingStrategy":"validation","validationCode":"// client-side countdown matching the 60s TTL\nlet ttl = 60;\nconst t = setInterval(() => { if (--ttl <= 0) { refreshCaptcha(); ttl = 60; } }, 1000);","typeGuard":null,"tryCatchPattern":"// AuthenticationFailureHandler shows '验证码已过期，请刷新'; prompt re-fetch.","preventionTips":["Auto-refresh the captcha before expiry.","Show a countdown to the user.","Tune expireIn to realistic think-time."],"tags":["spring-security","captcha","session","validation","expiry","java"],"backgroundTag":null,"analyzedSha":"614d2578d9495acf53cc02f2dee9c6131cc5e51a","analyzedAt":"2026-08-14T04:40:03.488Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}