You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用CSRF后出现403认证错误的排查与解决求助

解决Spring Boot + Svelte启用CSRF后POST /auth/signin 403问题

问题背景

技术栈为Java Spring Boot、Svelte,启用CSRF防护后,调用POST /auth/signin接口时收到403 Full authentication is required to access this resource错误。具体操作流程:

  1. 登录前先发送GET /csrf请求获取CSRF token,响应格式如下:
{
  "token":"d4cb2245-be82-4b61-ace5-8d52c6068182",
  "parameterName":"_csrf",
  "headerName":"X-XSRF-TOKEN"
}
  1. 将token放入X-XSRF-TOKEN请求头后发送POST /auth/signin,仍触发错误。

后端已配置:

  • 开启CSRF,使用CookieCsrfTokenRepository,/csrf和/auth/**路径已放行;禁用CSRF可正常访问
  • 提供CsrfController处理GET /csrf请求

前端已实现获取CSRF token并加入请求头的逻辑,尝试添加有效Authorization头仍报错。开启Spring Security TRACE日志后,发现提示Invalid CSRF token found for http://127.0.0.1:8080/auth/signin,但用Postman携带X-XSRF-TOKEN头和Cookie: XSRF-TOKEN可正常访问,推测前端请求未携带Cookie。

核心原因

Spring Security的CookieCsrfTokenRepository验证逻辑要求:请求必须同时携带**X-XSRF-TOKEN请求头和XSRF-TOKEN Cookie**,两者值一致才会通过验证。Postman会自动保存并发送Cookie,但前端请求默认不会携带Cookie,导致验证失败。

解决方案

1. Svelte前端配置:确保请求携带Cookie

无论是同域还是跨域请求,都需要显式配置请求携带凭证:

  • 如果用原生fetch,添加credentials: 'include'参数
  • 如果用axios,添加withCredentials: true参数

示例代码(原生fetch):

// 获取CSRF token的请求,必须携带Cookie才能让后端设置XSRF-TOKEN Cookie
async function getCsrf() {
  const response = await fetch('/csrf', {
    credentials: 'include'
  });
  return response.json();
}

// 登录请求,同时携带X-XSRF-TOKEN头和Cookie
async function signin(userData) {
  const csrfData = await getCsrf();
  const response = await fetch('/auth/signin', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-XSRF-TOKEN': csrfData.token
    },
    credentials: 'include', // 关键:携带Cookie
    body: JSON.stringify(userData)
  });
  return response;
}

2. 后端跨域配置(如果前端和后端跨域)

如果前端运行在不同域名/端口(比如Svelte默认的http://localhost:5173,后端在http://localhost:8080),需要在Spring Boot中配置CORS允许携带凭证:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // 允许前端读取Cookie
            )
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/csrf", "/auth/**").permitAll()
                .anyRequest().authenticated()
            )
            .cors(cors -> cors.configurationSource(corsConfigurationSource())); // 启用CORS配置
        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(List.of("http://localhost:5173")); // 替换为你的前端实际域名
        config.setAllowedMethods(List.of("GET", "POST", "OPTIONS"));
        config.setAllowedHeaders(List.of("*"));
        config.setAllowCredentials(true); // 必须设置为true,允许携带Cookie
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }
}

3. 排查验证步骤

  1. 打开浏览器开发者工具(F12),切换到Network标签:
    • 查看GET /csrf请求的Response Headers,确认存在Set-Cookie: XSRF-TOKEN=xxx
    • 查看POST /auth/signin请求的Request Headers,确认:
      • 携带Cookie: XSRF-TOKEN=xxx
      • X-XSRF-TOKEN头的值和Cookie中的值一致
  2. 若跨域,检查Response Headers中的Access-Control-Allow-Credentials是否为true,Access-Control-Allow-Origin是否是前端的具体域名(不能用*)

内容的提问来源于stack exchange,提问作者Chatchawan U-patham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 03:50:21