Spring Security 6中permitAll()路径POST请求返回401未授权问题
解决Spring Security 6中permitAll路径POST请求401问题(保留CSRF保护)
问题本质
Spring Security默认会对所有非GET/HEAD/TRACE/OPTIONS的HTTP请求执行CSRF令牌校验,permitAll()仅绕过认证校验,不会跳过CSRF校验。这就是关闭CSRF保护后请求正常,但开启时公开路径POST请求返回401的核心原因。
解决方案一:对公开路径跳过CSRF校验(推荐给无状态公开接口)
如果你的permitAll路径是无需CSRF保护的公开接口(比如注册、登录、第三方回调),可直接配置Spring Security忽略这些路径的CSRF校验:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/public/api/**", "/auth/register").permitAll() // 替换为你的公开路径 .anyRequest().authenticated() ) .csrf(csrf -> csrf .ignoringRequestMatchers("/public/api/**", "/auth/register") // 跳过指定路径的CSRF校验 ); return http.build(); }
解决方案二:为公开路径传递CSRF令牌(适合需要CSRF保护的公开接口)
如果公开接口也需要CSRF保护,需在请求时携带CSRF令牌,步骤如下:
- 配置CSRF令牌通过Cookie传递:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/public/api/**", "/auth/register").permitAll() .anyRequest().authenticated() ) .csrf(csrf -> csrf .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // 允许前端读取CSRF Cookie ); return http.build(); }
- Postman测试步骤:
- 先发送一个GET请求到你的公开路径(比如
GET /public/api/health),从响应Cookie中获取XSRF-TOKEN的值 - 在POST请求的Headers中添加
X-XSRF-TOKEN,值为刚才获取的令牌内容 - 发送POST请求即可通过校验
- 先发送一个GET请求到你的公开路径(比如
额外排查点
- 确认
requestMatchers的路径匹配规则是否正确,比如是否遗漏了斜杠、是否匹配到了子路径 - 查看Spring Security日志,若出现
Invalid CSRF token found for...,说明是令牌缺失或无效,可针对性调整
内容的提问来源于stack exchange,提问作者Octavia
相关产品推荐
相关产品推荐

