Spring Security下POST请求`/users/registration/create`返回403求助
问题:未登录用户POST请求注册端点返回403错误
允许未登录用户向/users/registration/create端点发送POST请求。已配置SecurityFilterChain放行/users/registration/**路径,GET请求/users/registration/form可正常加载,但提交表单发送POST请求至该创建端点时,浏览器返回403错误。
安全配置代码
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((requests) -> requests .requestMatchers( "/users/registration/**").permitAll() ); return http.build(); }
控制器代码
@Controller public class UserRegistrationsController { @Autowired private AppUserService appUserService; @GetMapping("/users/registration/form") public String newRegistration(WebRequest request, Model model) { AppUserDto appUserDto = new AppUserDto(); model.addAttribute("user", appUserDto); return "users/registration"; } @PostMapping("/users/registration/create") public void createRegistration( @ModelAttribute("user") @Valid AppUserDto appUserDto, HttpServletRequest request, Errors errors ) { try { AppUser registered = appUserService.registerNewUserAccount(appUserDto); } catch (AppUserAlreadyExistsException ex) { } } }
尝试过的配置
@Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests((authorize) -> { authorize.requestMatchers("/", "/users/registration/**").permitAll(); }); http.csrf().disable(); return http.build(); }
问题原因与正确解决方式
原因
Spring Security默认开启CSRF防护机制,对于POST、PUT、DELETE等具有修改性质的请求,必须携带合法的CSRF令牌才能通过校验。你虽然配置了路径权限放行,但CSRF校验依然生效,导致POST请求被拦截返回403。
方案1:在表单中添加CSRF令牌(推荐)
无需全局禁用CSRF,只需在注册表单中添加Spring Security提供的CSRF令牌字段即可:
- 若使用Thymeleaf模板:
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
- 若使用普通JSP:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
方案2:仅对注册端点跳过CSRF校验(不推荐全局禁用)
如果不想在表单中添加令牌,可以针对特定路径单独跳过CSRF校验,避免全局禁用带来的安全风险:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((requests) -> requests .requestMatchers("/users/registration/**").permitAll() .anyRequest().authenticated() ) .csrf((csrf) -> csrf .ignoringRequestMatchers("/users/registration/create") ); return http.build(); }
注意:全局禁用CSRF会大幅降低系统安全性,仅建议在测试环境临时使用,生产环境优先选择方案1。
内容的提问来源于stack exchange,提问作者Blaine Lafreniere
相关产品推荐
相关产品推荐

