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

Spring Security认证对象跨控制器/请求不持久问题咨询

Spring Security跨请求Authentication丢失问题解决方案

核心原因

你遇到的认证信息跨请求丢失,本质是Spring Security的上下文持久化机制没有正确执行,常见触发点包括手动操作Session时Key不匹配、过滤链未正确加载上下文、跨域场景下Session未正常传递三类。

修复步骤

  • 移除手动操作HttpSession存SecurityContext的逻辑,改用Spring Security官方提供的持久化组件操作,避免常量值不匹配问题。登录逻辑中认证完成后按如下方式处理:
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(username, "password", privileges);
Authentication auth = authenticationManager.authenticate(authToken);
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(auth);
// 用官方默认的Session持久化仓库存储上下文,无需手动拼常量操作Session
new HttpSessionSecurityContextRepository().saveContext(sc, request, response);
  • 补全安全配置中的Session管理规则,明确指定Session创建策略,避免框架默认配置被覆盖:
@Order(1)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Conditional(OpenSecurityCondition.class)
public class OpenSecurityConfig extends WebSecurityConfigurerAdapter {

    private final PasswordEncoder passwordEncoder;

    public OpenSecurityConfig(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }
    
    @Bean("authenticationManager")
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
          http
                  .csrf().disable()
                  // 明确指定Session策略:需要时创建会话,用于存储认证上下文
                  .sessionManagement()
                      .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                      .and()
                  .authorizeRequests()
                  .anyRequest()
                  .permitAll();
    }
}
  • 排查跨域请求的Cookie传递配置:如果前后端不同源,前端请求需要开启携带凭证配置(例如axios设置withCredentials: true),后端CORS配置需要开启allowCredentials(true),否则浏览器不会存储服务端返回的JSESSIONID,每次请求都会生成全新的匿名会话,自然读不到之前的认证信息。
  • 不要手动构造带null凭证的未经过AuthenticationManager校验的Token直接塞入上下文:三个参数的UsernamePasswordAuthenticationToken构造器虽然会直接标记为已认证,但未走官方认证流程的Token可能会被安全过滤器判定为不可信,在请求处理过程中被重置为匿名用户。

为什么持久化逻辑没有默认生效

SecurityContext默认不会自动跨请求传递,这是Spring Security的设计逻辑,不是bug:

  • SecurityContextHolder默认采用ThreadLocal策略存储认证信息,存储内容和当前请求线程绑定,请求结束后线程会被Tomcat等容器回收复用,ThreadLocal中的内容会被清空,不会自动保留到下一个请求。
  • 跨请求的上下文持久化完全依赖SecurityContextPersistenceFilter这个请求过滤器:它会在请求进入过滤链时,从配置的持久化仓库(默认是HttpSession)读取之前存储的SecurityContext绑定到当前线程的ThreadLocal;请求处理完成后,再把当前线程的SecurityContext存回持久化仓库,同时清空ThreadLocal避免线程复用导致的信息泄露。
  • 这个过滤器只有在请求匹配到Spring Security过滤链时才会执行:如果你的配置类条件注解@Conditional(OpenSecurityCondition.class)在部分请求场景下不生效、或者你手动把Session策略设为了STATELESS(无状态模式,常用于JWT鉴权场景)、或者你手动存Session时用的Key和框架默认读取的Key(SPRING_SECURITY_CONTEXT)不一致,过滤器就读取不到之前存的认证信息,会自动创建空上下文填充anonymousUser匿名身份。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 21:15:19