Spring Boot 3 带安全校验的POST方法重定向403异常问题
问题现象
在Spring Boot 3环境下,提交POST请求到带路径变量的受保护路径/home/1234,未登录时会正常跳转至登录页,但输入默认凭据登录后出现403错误;而在Spring Boot 2环境中,将requestMatchers替换为mvcMatchers即可正常完成登录并重定向到目标页面。
代码复现
//skipped imports @SpringBootApplication @Controller public class SpringMvcExampleApplication { public static void main(String[] args) { SpringApplication.run(SpringMvcExampleApplication.class, args); } } @RestController class IndexController { @GetMapping("/") public String index() { return """ <form method="post" action="/home/1234"> <input type="submit" value="post"/> </form> """; } } @Controller @RequestMapping("/home") class HomeController { @GetMapping @ResponseBody String homeGet() { return "<h1>Hello</h1>"; } @PostMapping("/{id}") String homePost(@PathVariable String id) { return "redirect:/home"; } } @Configuration class Config { @Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http .formLogin() .and() .csrf(cfg -> cfg.disable()) .authorizeHttpRequests(authorize -> authorize .requestMatchers("/").permitAll() .requestMatchers("/home/**").authenticated() ) .build(); } }
问题原因
Spring Boot 3中,requestMatchers(String...)默认使用AntPathRequestMatcher,它基于Ant路径规则匹配原始请求URL;而Spring Boot 2中的mvcMatchers使用的是MvcRequestMatcher,会遵循Spring MVC的路径解析规则(如路径变量解析、请求映射匹配逻辑)。
两者核心差异在于:
- AntPathRequestMatcher仅匹配原始URL字符串,不会考虑Spring MVC对路径的解析(比如不会识别
/home/{id}这类路径变量模式,仅做字符串匹配) - MvcRequestMatcher会结合Spring MVC的
HandlerMapping逻辑,准确匹配被Spring MVC处理的路径模式
当登录成功后,Spring Security会重放原始的POST请求/home/1234,随后控制器返回redirect:/home,浏览器发起GET请求到/home。此时AntPathRequestMatcher的/home/**看似能匹配/home,但由于Spring Boot 3中Security与MVC路径匹配逻辑的分离,导致授权规则未被正确触发,最终返回403。
解决方案
在Spring Boot 3中,需要显式使用MvcRequestMatcher来替代原有的字符串requestMatchers,确保Security的路径匹配与Spring MVC的逻辑一致:
@Configuration class Config { @Bean SecurityFilterChain securityFilterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception { // 创建MvcRequestMatcher构建器,关联Spring MVC的路径解析逻辑 MvcRequestMatcher.Builder mvcMatcher = new MvcRequestMatcher.Builder(introspector); return http .formLogin() .and() .csrf(cfg -> cfg.disable()) .authorizeHttpRequests(authorize -> authorize .requestMatchers(mvcMatcher.pattern("/")).permitAll() // 使用MvcRequestMatcher匹配/home/**路径 .requestMatchers(mvcMatcher.pattern("/home/**")).authenticated() ) .build(); } }
这样配置后,Security会遵循Spring MVC的路径匹配规则,无论是带路径变量的/home/1234,还是重定向后的/home,都会被正确识别为受保护路径并允许已认证用户访问。
内容的提问来源于stack exchange,提问作者Sandro J

