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

基于Cookie的Spring Security前端会话维持问题求助

解决React前端无法自动保存Spring Security会话Cookie的问题

看起来你遇到了跨域请求下会话Cookie无法自动维护的典型问题——Postman会自动处理Cookie,但浏览器出于安全限制,在跨域场景下不会自动保存或携带Cookie,除非前后端都做了正确配置。咱们一步步来解决:

核心问题:跨域请求的Cookie限制

浏览器的同源策略会阻止跨域请求自动携带Cookie,同时默认不允许JS读取跨域响应的Set-Cookie头(尤其是Spring Session默认的HttpOnly Cookie,这是安全设置)。这就是你看到document.cookie为空、response.headers.get('Set-Cookie')为null的原因——不是Cookie没返回,是浏览器不让你读,也没自动存。

解决方案:前后端配合开启跨域凭证支持

1. 后端Spring Security配置CORS

你需要在Spring Security中明确配置跨域规则,允许前端域名的请求携带凭证。修改你的SpringSecurityConfig:

@EnableWebSecurity
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private AuthenticationProviderService authenticationProviderService;

    // 新增CORS配置Bean
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // 替换成你的前端实际域名+端口,比如http://localhost:3000,不能用*(带凭证不允许通配符)
        configuration.setAllowedOrigins(Arrays.asList("http://your-frontend-url:port"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        // 关键:允许携带凭证(Cookie)
        configuration.setAllowCredentials(true);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors() // 启用CORS配置
            .and()
            .authorizeRequests()
                .antMatchers("/customer/register").permitAll()
                .anyRequest().fullyAuthenticated()
            .and()
            .formLogin()
                .permitAll()
                .defaultSuccessUrl("/customer/home", false)
            .and()
            .logout()
                .permitAll()
            .and()
            .httpBasic();
        http.csrf().disable();
    }
    //[ . . . ]
}

2. 前端React请求添加凭证参数

修改你的fetch请求,加上credentials: 'include',告诉浏览器在跨域请求中携带/保存Cookie:

const mw = store => next => action => {
    if(action.type == 'SUBMIT_LOGIN_USER') {
        var payload = { username: action.user.username, password: action.user.password };
        // Build formData object.
        let formData = new FormData();
        formData.append('username', action.user.username);
        formData.append('password', action.user.password);
        return fetch('http://192.168.0.34:8080/login', {
            method: 'POST',
            body: formData,
            credentials: 'include' // 新增这一行,关键配置!
        }).then( r => (r) )
        .then(function(response) {
            // 浏览器会自动保存HttpOnly Cookie,无需手动读取Set-Cookie
            console.log(document.cookie) // 若Cookie非HttpOnly,此处会显示会话Cookie(建议保持HttpOnly)
            next(action)
        })
        .catch(function(err) {
            console.info(err);
        });
    } else {
        next(action)
    }
}

3. 后续请求的注意事项

登录成功后,所有后续向后端发起的API请求(比如跳转后的GET /customer/home)都需要加上credentials: 'include',这样浏览器才会自动携带会话Cookie,后端就能识别用户身份,不会返回403。

关于是否改用认证令牌(JWT)

Cookie-Session模式完全可以正常工作,而且默认的HttpOnly Cookie比前端存储JWT更安全(能避免XSS攻击窃取令牌)。如果你的系统是单体应用,Cookie模式足够用;如果是分布式微服务架构,JWT可能更适合(无需服务器存储会话)。但当前问题的核心是跨域配置,不是方案选型——先把Cookie模式跑通再考虑是否切换。

额外说明

  • Spring Session默认的会话Cookie是HttpOnly的,这是安全最佳实践,所以JS无法读取它,但浏览器会自动在请求中携带,完全不影响会话维护。
  • 不要为了让JS读取Cookie而关闭HttpOnly,这会引入XSS风险。

内容的提问来源于stack exchange,提问作者bohemian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:18:04