{"record":{"id":"e11f162de58c7cc1","repo":"wuyouzhuguli/SpringAll","slug":"error-e11f16","errorCode":null,"errorMessage":"验证码不能为空！","messagePattern":"验证码不能为空！","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"65.Spring-Security-OAuth2-Config/src/main/java/cc/mrbird/security/validate/smscode/SmsCodeFilter.java","lineNumber":49,"sourceCode":"                && StringUtils.equalsIgnoreCase(httpServletRequest.getMethod(), \"post\")) {\n            try {\n                validateCode(new ServletWebRequest(httpServletRequest));\n            } catch (Exception e) {\n                authenticationFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, new AuthenticationServiceException(e.getMessage()));\n                return;\n            }\n        }\n        filterChain.doFilter(httpServletRequest, httpServletResponse);\n    }\n\n    private void validateCode(ServletWebRequest servletWebRequest) throws Exception {\n        String smsCodeInRequest = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), \"smsCode\");\n        String mobileInRequest = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), \"mobile\");\n\n        String codeInRedis = redisCodeService.get(servletWebRequest, mobileInRequest);\n\n        if (StringUtils.isBlank(smsCodeInRequest)) {\n            throw new Exception(\"验证码不能为空！\");\n        }\n        if (codeInRedis == null) {\n            throw new Exception(\"验证码已过期！\");\n        }\n        if (!StringUtils.equalsIgnoreCase(codeInRedis, smsCodeInRequest)) {\n            throw new Exception(\"验证码不正确！\");\n        }\n        redisCodeService.remove(servletWebRequest, mobileInRequest);\n\n    }\n}","sourceCodeStart":31,"sourceCodeEnd":60,"githubUrl":"https://github.com/wuyouzhuguli/SpringAll/blob/614d2578d9495acf53cc02f2dee9c6131cc5e51a/65.Spring-Security-OAuth2-Config/src/main/java/cc/mrbird/security/validate/smscode/SmsCodeFilter.java#L31-L60","documentation":"A plain java.lang.Exception with message '验证码不能为空！' (SMS code cannot be empty) is thrown by SmsCodeFilter.validateCode when the request carries no 'smsCode' parameter. The filter runs before the SMS authentication provider, so this is the input-validation gate of the SMS login flow. Throwing a raw Exception (rather than an AuthenticationException) is a code smell — it bypasses Spring Security's failure handler and produces a generic 500 unless the filter is wrapped.","triggerScenarios":"A POST to the SMS login endpoint omits the 'smsCode' request parameter, or sends it empty/whitespace-only, so ServletRequestUtils.getStringParameter returns a blank value and StringUtils.isBlank is true. Any client (browser form missing the field, curl without -d smsCode=, or a frontend bug dropping the input) triggers it.","commonSituations":"Frontend form forgot to include the smsCode input name; the field was disabled or cleared before submit; the parameter name was renamed (e.g. 'code' vs 'smsCode') and the client/server disagree; or a bot/automated request hits the endpoint without the field.","solutions":["Ensure the client sends a non-empty 'smsCode' form parameter matching the field name the filter reads via ServletRequestUtils.getStringParameter(request, \"smsCode\").","Standardize the parameter name across client and filter — if the frontend posts 'code', align the filter's getStringParameter argument or update the client.","Replace the generic 'throw new Exception' with an AuthenticationException subclass (e.g. a custom ValidateCodeException) so Spring's AuthenticationFailureHandler renders a proper 4xx instead of a 500.","Add client-side required-field validation on the smsCode input to prevent submission of empty values."],"exampleFix":"// before\nif (StringUtils.isBlank(smsCodeInRequest)) {\n    throw new Exception(\"验证码不能为空！\");\n}\n\n// after — typed exception routed through the security failure handler\nif (StringUtils.isBlank(smsCodeInRequest)) {\n    throw new ValidateCodeException(\"验证码不能为空！\");\n}","handlingStrategy":"validation","validationCode":"// Client/server guard before invoking the filter chain\nString smsCode = request.getParameter(\"smsCode\");\nif (smsCode == null || smsCode.trim().isEmpty()) {\n    response.sendError(HttpServletResponse.SC_BAD_REQUEST, \"smsCode 参数缺失\");\n    return; // do not proceed to validateCode\n}","typeGuard":"private boolean hasSmsCode(HttpServletRequest req) {\n    String c = req.getParameter(\"smsCode\");\n    return c != null && !c.trim().isEmpty();\n}","tryCatchPattern":"try {\n    filterChain.doFilter(request, response);\n} catch (Exception e) {\n    if (\"验证码不能为空！\".equals(e.getMessage())) {\n        response.sendError(400, \"验证码不能为空\");\n    } else {\n        throw e;\n    }\n}","preventionTips":["Mark the smsCode input required on the frontend and disable submit until filled.","Keep the request parameter name ('smsCode') consistent across client and filter.","Throw a typed AuthenticationException (e.g. ValidateCodeException) so the security failure handler returns a 4xx, not a raw Exception that yields 500."],"tags":["spring-security","sms-code","input-validation","filter","request-parameter"],"backgroundTag":null,"analyzedSha":"614d2578d9495acf53cc02f2dee9c6131cc5e51a","analyzedAt":"2026-08-14T04:40:03.488Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}