Spring Session JDBC未存储Angular调用接口的会话问题
核心原因:会话创建的触发逻辑差异
两种场景的本质区别在于Spring Security是否触发了会话的主动创建及认证信息的持久化:
浏览器直接访问场景:
首次请求未携带Authorization头,Spring Security返回401 Unauthorized并附带WWW-Authenticate: Basic响应头,触发浏览器弹出认证弹窗。用户输入凭证后,浏览器再次发送请求并携带Authorization头,此时Spring Security不仅验证凭证,还会主动创建会话并将认证信息存入会话——这是因为浏览器后续请求会依赖会话ID(通过Cookie传递)维持认证状态,Spring Security默认会生成会话并写入JDBC存储。Angular主动携带
Authorization头场景:
Angular请求直接携带完整的Authorization: Basic xxx头,Spring Security仅需验证该头有效性即可完成认证,没有触发会话创建的必要条件。默认情况下,Spring Security的会话创建策略是IF_REQUIRED(仅在需要时创建),如果你的请求是无状态的(即每次请求自行携带认证头),Spring会判定无需会话维持状态,因此不会生成会话,自然也不会将会话数据写入JDBC存储。
验证与解决方向
调整会话创建策略配置
若需要强制为带Authorization头的请求创建会话,可显式修改Spring Security配置:@Override protected void configure(HttpSecurity http) throws Exception { http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.ALWAYS); // 强制为所有请求创建会话 // 其他认证、授权配置... }若仅需为认证后的请求创建会话,可保留
IF_REQUIRED策略,结合后续手动触发逻辑。手动触发会话存储
通过自定义AuthenticationSuccessHandler,在认证成功后强制创建会话并存储认证信息:@Component public class CustomAuthSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 将认证信息存入上下文 SecurityContextHolder.getContext().setAuthentication(authentication); // 强制创建会话(参数true表示不存在则创建) request.getSession(true); // 按需处理响应,比如返回用户信息 response.setStatus(HttpServletResponse.SC_OK); } }然后在Security配置中关联该处理器:
@Override protected void configure(HttpSecurity http) throws Exception { http .httpBasic() .successHandler(customAuthSuccessHandler); // 其他配置... }确认JDBC会话存储配置正确性
检查是否已正确配置spring.session.store-type=jdbc,且通过org.springframework.session.jdbc.schema-*.sql脚本初始化了会话存储所需的数据库表结构。
内容的提问来源于stack exchange,提问作者steeve

