{"record":{"id":"1dcbcacdc305b2f0","repo":"lenve/vhr","slug":"authentication-method-not-supported-request-getm","errorCode":null,"errorMessage":"Authentication method not supported: {request.getMethod()}","messagePattern":"Authentication method not supported: (.+?)","errorType":"exception","errorClass":"AuthenticationServiceException","httpStatus":null,"severity":"warning","filePath":"vhr/vhrserver/vhr-web/src/main/java/org/javaboy/vhr/config/LoginFilter.java","lineNumber":34,"sourceCode":"import java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @作者 江南一点雨\n * @微信公众号 江南一点雨\n * @网站 http://www.javaboy.org\n * @微信 a_java_boy\n * @GitHub https://github.com/lenve\n * @Gitee https://gitee.com/lenve\n */\npublic class LoginFilter extends UsernamePasswordAuthenticationFilter {\n    @Autowired\n    SessionRegistry sessionRegistry;\n    @Override\n    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {\n        if (!request.getMethod().equals(\"POST\")) {\n            throw new AuthenticationServiceException(\n                    \"Authentication method not supported: \" + request.getMethod());\n        }\n        String verify_code = (String) request.getSession().getAttribute(\"verify_code\");\n        if (request.getContentType().contains(MediaType.APPLICATION_JSON_VALUE) || request.getContentType().contains(MediaType.APPLICATION_JSON_UTF8_VALUE)) {\n            Map<String, String> loginData = new HashMap<>();\n            try {\n                loginData = new ObjectMapper().readValue(request.getInputStream(), Map.class);\n            } catch (IOException e) {\n            }finally {\n                String code = loginData.get(\"code\");\n                checkCode(response, code, verify_code);\n            }\n            String username = loginData.get(getUsernameParameter());\n            String password = loginData.get(getPasswordParameter());\n            if (username == null) {\n                username = \"\";\n            }\n            if (password == null) {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/lenve/vhr/blob/03abbd35af24e55368ce4e09f4038dc2aba3ff5f/vhr/vhrserver/vhr-web/src/main/java/org/javaboy/vhr/config/LoginFilter.java#L16-L52","documentation":"Thrown by the overridden UsernamePasswordAuthenticationFilter.attemptAuthentication when the HTTP method of the incoming request is not POST. UsernamePasswordAuthenticationFilter is contract-bound to POST form/json credentials; LoginFilter preserves that contract and rejects GET (or any other verb) immediately with an AuthenticationServiceException before parsing the body or verifying the captcha.","triggerScenarios":"A GET request (e.g., a browser navigation, a link, or a misconfigured fetch) hits the configured login-processing URL (default /doLogin or /login). The first guard in attemptAuthentication compares request.getMethod() to 'POST', and on mismatch throws AuthenticationServiceException with the actual method name interpolated into the message.","commonSituations":"Front-end developer used axios.get or fetch without method:'POST' for the login call; a browser pre-filled the login URL into the address bar and someone hit Enter; a redirect from an intercepting filter converted the POST to GET; a proxy/load balancer rewrites the method; Spring Security's loginProcessingUrl was triggered by a navigation rather than a form action; CORS preflight (OPTIONS) reached this filter.","solutions":["Change the login request to POST: in the front-end use axios.post('/doLogin', data) or fetch(url, { method: 'POST', body: ... }).","Ensure the form's method attribute is 'post' (method='post') if using a traditional HTML form submit to the login URL.","If a reverse proxy is in front, confirm it preserves the HTTP method and is not rewriting POST to GET (check X-Forwarded-* and proxy config).","Allow CORS preflight by ensuring the OPTIONS method is permitted/short-circuited before reaching this filter (configure CORS filter ordering).","Verify the configured loginProcessingUrl matches the URL the client targets so the POST actually lands here."],"exampleFix":"// before\naxios.get('/doLogin', { params: { username, password } });\n// after\naxios.post('/doLogin', { username, password, code });","handlingStrategy":"validation","validationCode":"// Front-end: assert the method before sending.\nfunction login(payload) {\n  // UsernamePasswordAuthenticationFilter requires POST\n  return axios.post('/doLogin', payload); // never axios.get here\n}","typeGuard":"// Java: a guard inside the filter to give a cleaner message (optional; the throw is correct).\nString method = request.getMethod();\nif (!\"POST\".equalsIgnoreCase(method)) {\n    response.setStatus(405);\n    response.setHeader(\"Allow\", \"POST\");\n    return; // or keep the existing throw\n}","tryCatchPattern":"// Not typically caught per-request; configure the framework instead.\n// Ensure the loginProcessingUrl is only reachable via POST by mapping it on POST only,\n// and let AuthenticationServiceException flow to the failure handler:\n// http.formLogin().loginProcessingUrl(\"/doLogin\")  // Spring binds POST by default\n// Add a 405 fallback for non-POST so clients get a clear signal:\n@Override\npublic void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp,\n                                    AuthenticationException ex) {\n    if (ex instanceof AuthenticationServiceException\n        && ex.getMessage().startsWith(\"Authentication method not supported\")) {\n        resp.setStatus(405);\n    }\n}","preventionTips":["Pin the login call to POST in a single front-end service method and reuse it — never hand-write the login request.","Document the login endpoint as POST-only in the API contract.","Add an OPTIONS/CORS preflight allowance so preflight never reaches this filter.","Write an integration test asserting GET on the login URL returns 405/401, not 200."],"tags":["spring-security","authentication","filter","http-method","login"],"backgroundTag":null,"analyzedSha":"03abbd35af24e55368ce4e09f4038dc2aba3ff5f","analyzedAt":"2026-08-14T04:43:34.269Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}