Spring REST端点创建会话异常:认证后访问受保护端点被重定向
咱们一步步来排查这个会话认证的问题,大概率是Spring Security的会话配置或者自定义认证端点的处理逻辑没衔接好,我整理了几个常见的遗漏点:
1. 确保自定义认证端点正确完成Spring Security的认证流程
你手动调用session.getSession(true)只是创建了空会话,但Spring Security并没有把这个会话和已认证的用户身份关联起来。这就导致后续请求过来时,Security上下文里没有有效认证信息,自然会触发重定向到登录入口。
- 你需要在验证用户名密码成功后,手动构建并绑定认证信息到Security上下文和当前会话:
// 假设已完成用户名密码校验,构建包含权限的Authentication对象 UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(validUsername, null, userAuthorities); // 将认证信息存入Security上下文 SecurityContextHolder.getContext().setAuthentication(authToken); // 把上下文持久化到当前会话,让后续请求能读取到 HttpSessionSecurityContextRepository contextRepo = new HttpSessionSecurityContextRepository(); contextRepo.saveContext(SecurityContextHolder.getContext(), request, response); - 注意:务必确保代码里的
request和response是当前请求的真实对象,否则会话绑定会失效。
2. 检查Spring Security的会话管理配置
Spring Security默认会接管会话生命周期,但如果你的自定义认证绕开了它的默认流程,需要调整配置来匹配你的手动会话创建逻辑:
Spring Security 5.7之前(含WebSecurityConfigurerAdapter)
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http // 配置会话创建策略为按需创建,和你手动调用getSession(true)的逻辑匹配 .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .and() // 放行自定义登录端点,避免被拦截 .authorizeRequests() .antMatchers("/your-custom-login-endpoint").permitAll() .anyRequest().authenticated() .and() .exceptionHandling() .authenticationEntryPoint(yourCustomEntryPoint); // 你的自定义入口点 } }
Spring Security 5.7+(无WebSecurityConfigurerAdapter)
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .sessionManagement(sm -> sm .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) ) .authorizeHttpRequests(auth -> auth .requestMatchers("/your-custom-login-endpoint").permitAll() .anyRequest().authenticated() ) .exceptionHandling(ex -> ex .authenticationEntryPoint(yourCustomEntryPoint) ); return http.build(); }
3. 验证JSESSIONID的传递是否正确
- 确保客户端在请求受保护端点时,正确携带了服务器返回的JSESSIONID Cookie。可以用浏览器开发者工具(Network标签)查看请求头的
Cookie字段,确认包含JSESSIONID=xxx的内容。 - 如果是跨域场景,还要额外配置:
- Spring Security中开启CORS并允许凭证:
http.cors(cors -> cors.configurationSource(corsConfigSource)),其中corsConfigSource要设置allowCredentials(true)。 - 前端请求需携带凭证,比如axios要设置
withCredentials: true。
- Spring Security中开启CORS并允许凭证:
4. 检查SecurityContext的存储与读取逻辑
Spring Security默认使用HttpSessionSecurityContextRepository来存储SecurityContext,如果你的配置替换了这个组件,或者有自定义过滤器干扰了上下文读取,也会导致认证失败:
- 不要随意自定义
SecurityContextRepository,除非你明确理解其作用;如果已经自定义,要确保它能正确从会话中读取和写入SecurityContext。 - 检查过滤器链顺序:自定义的认证逻辑(比如你的登录端点)要在Spring Security的核心认证过滤器之前执行,确保后续过滤器能读取到已绑定的认证信息。
如果以上排查都没解决问题,可以提供你的Security配置类完整代码、自定义登录端点的代码,这样能更精准定位问题。
内容的提问来源于stack exchange,提问作者venkatReddi
相关产品推荐
相关产品推荐

