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

Spring Security问题:表单登录后无法通过AJAX访问/api接口

解决方案

问题出在你的apiFilterChain配置了无状态(STATELESS)会话管理,这会让Spring Security完全忽略已有的登录会话,所以即使通过表单登录创建了会话,访问/api/**时仍会强制要求Basic认证。要让表单登录的用户直接访问API,需要调整配置让API过滤器链同时支持会话认证和Basic认证。

调整SecurityConfig配置

修改apiFilterChain

将会话创建策略从STATELESS改为IF_REQUIRED,允许Spring Security读取已有的表单登录会话,同时保留Basic认证支持:

@Bean
public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
    http
        .securityMatcher("/api/**")
        .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
        // 保留Basic认证,供未通过表单登录的客户端使用
        .httpBasic(Customizer.withDefaults())
        // 允许使用已有的会话认证,不再强制无状态
        .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
        // 配置CSRF,适配AJAX请求
        .csrf(csrf -> csrf
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        );
    return http.build();
}

确保formFilterChain的CSRF配置正确

表单登录后,AJAX请求API需要携带CSRF令牌,所以在formFilterChain中开启Cookie存储的CSRF令牌(允许前端读取):

@Bean
public SecurityFilterChain formFilterChain(HttpSecurity http) throws Exception {
    http
        .securityMatcher("/**")
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/login").permitAll()
            .anyRequest().authenticated()
        )
        .formLogin(form -> form
            .loginPage("/login")
            .defaultSuccessUrl("/home")
            .permitAll()
        )
        .logout(logout -> logout.permitAll())
        .csrf(csrf -> csrf
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        );
    return http.build();
}

前端AJAX请求适配

由于启用了CSRF保护,AJAX请求/api/**时需要携带CSRF令牌。可以从Cookie中读取XSRF-TOKEN,并添加到请求头X-XSRF-TOKEN中:

// 工具函数:获取Cookie值
function getCookie(name) {
    let value = "; " + document.cookie;
    let parts = value.split("; " + name + "=");
    if (parts.length === 2) return parts.pop().split(";").shift();
}

// 发起AJAX请求示例
$.ajax({
    url: "/api/your-endpoint",
    type: "GET",
    headers: {
        "X-XSRF-TOKEN": getCookie("XSRF-TOKEN")
    },
    success: function(response) {
        // 处理响应
    }
});

原理说明

  • 调整会话策略后,apiFilterChain会优先检查请求是否携带已登录的会话:如果有,直接使用会话中的认证信息;如果没有,再要求Basic认证。
  • CSRF配置确保AJAX请求不会被Spring Security拦截,符合表单登录场景下的安全规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 00:00:57