{"record":{"id":"b8b2366d8de7ffed","repo":"xkcoding/spring-boot-demo","slug":"405","errorCode":"405","errorMessage":"请求方式不支持！","messagePattern":"请求方式不支持！","errorType":"exception","errorClass":"SecurityException","httpStatus":null,"severity":"warning","filePath":"demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/RbacAuthorityService.java","lineNumber":105,"sourceCode":"    /**\n     * 校验请求是否存在\n     *\n     * @param request 请求\n     */\n    private void checkRequest(HttpServletRequest request) {\n        // 获取当前 request 的方法\n        String currentMethod = request.getMethod();\n        Multimap<String, String> urlMapping = allUrlMapping();\n\n        for (String uri : urlMapping.keySet()) {\n            // 通过 AntPathRequestMatcher 匹配 url\n            // 可以通过 2 种方式创建 AntPathRequestMatcher\n            // 1：new AntPathRequestMatcher(uri,method) 这种方式可以直接判断方法是否匹配，因为这里我们把 方法不匹配 自定义抛出，所以，我们使用第2种方式创建\n            // 2：new AntPathRequestMatcher(uri) 这种方式不校验请求方法，只校验请求路径\n            AntPathRequestMatcher antPathMatcher = new AntPathRequestMatcher(uri);\n            if (antPathMatcher.matches(request)) {\n                if (!urlMapping.get(uri).contains(currentMethod)) {\n                    throw new SecurityException(Status.HTTP_BAD_METHOD);\n                } else {\n                    return;\n                }\n            }\n        }\n\n        throw new SecurityException(Status.REQUEST_NOT_FOUND);\n    }\n\n    /**\n     * 获取 所有URL Mapping，返回格式为{\"/test\":[\"GET\",\"POST\"],\"/sys\":[\"GET\",\"DELETE\"]}\n     *\n     * @return {@link ArrayListMultimap} 格式的 URL Mapping\n     */\n    private Multimap<String, String> allUrlMapping() {\n        Multimap<String, String> urlMapping = ArrayListMultimap.create();\n\n        // 获取url与类和方法的对应信息","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/xkcoding/spring-boot-demo/blob/87a142f9604c1a5365b4d24d22c2c11c26a9d5ab/demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/RbacAuthorityService.java#L87-L123","documentation":"Thrown by RbacAuthorityService.checkRequest when the request URL path matches a registered mapping but the HTTP method (GET/POST/PUT/DELETE etc.) is not in that mapping's allowed method list. This is a 405 Method Not Error. The SecurityException wraps Status.HTTP_BAD_METHOD (code 405). This fires during dynamic URL-based authorization before permission checking proceeds.","triggerScenarios":"Sending a request whose path matches a registered controller endpoint but using an HTTP verb that endpoint does not support — e.g., POST to an endpoint that only allows GET. The AntPathRequestMatcher matches on path only, then urlMapping.get(uri).contains(currentMethod) returns false.","commonSituations":"Frontend sends the wrong HTTP method (e.g., PUT instead of PATCH); API documentation is out of date; a proxy or gateway rewrites the method; curl/client using the wrong verb; new endpoint method not yet registered in the URL mapping.","solutions":["Check the API endpoint's allowed methods and use the correct HTTP verb.","Verify the @RequestMapping/@GetMapping/@PostMapping annotation on the target controller method.","Ensure no proxy/load balancer is rewriting the HTTP method.","Confirm the SecurityException is handled by a @ControllerAdvice that returns a 405 response."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Client-side: verify the endpoint accepts the HTTP method before sending\n// Use the actuator /mappings endpoint or OpenAPI spec to confirm allowed methods.\n// No runtime pre-check API in the security layer.","typeGuard":null,"tryCatchPattern":"// In a @ControllerAdvice handler for SecurityException\n@ExceptionHandler(SecurityException.class)\n@ResponseBody\npublic ResponseEntity<ApiResponse> handleSecurityException(SecurityException e) {\n    Status status = e.getStatus(); // or extract code/message\n    if (status.getCode() == 405) {\n        return ResponseEntity.status(405).body(ApiResponse.ofStatus(Status.HTTP_BAD_METHOD));\n    }\n    // ... handle other codes\n    return ResponseEntity.status(500).body(ApiResponse.ofStatus(Status.ERROR));\n}","preventionTips":["Always use the correct HTTP verb per the API specification.","Keep API documentation in sync with controller annotations.","Verify no proxy is rewriting the HTTP method.","Ensure the SecurityException handler maps code 405 to an HTTP 405 response."],"tags":["spring-security","rbac","http-method","http-405","authorization","url-mapping"],"backgroundTag":null,"analyzedSha":"87a142f9604c1a5365b4d24d22c2c11c26a9d5ab","analyzedAt":"2026-08-14T01:16:58.217Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}