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

Angular5+Spring REST每次请求生成新Session ID问题求助

刚遇到过类似的问题,这在Angular+Spring前后端分离架构里太常见了——本质就是会话Cookie没被正确传递,导致每次请求都触发新的Session。咱们一步步来解决:

一、先搞懂问题根源

Spring的HttpSession是靠浏览器携带的JSESSIONID Cookie来识别会话的,但Angular的HTTP请求默认不会自动带上Cookie;如果是跨域场景(比如Angular跑在localhost:4200,Spring在localhost:8080),浏览器的同源策略还会阻止Cookie跨域传递,双重原因导致每次请求都是新Session。

二、解决方案分步实施

1. 让Angular请求携带Cookie

在Angular的HTTP请求中必须显式设置withCredentials: true,这样才会把浏览器里的Cookie(包括JSESSIONID)随请求一起发送。

方式一:单个请求配置

import { HttpClient } from '@angular/common/http';

constructor(private http: HttpClient) {}

loadControls(userId: string) {
  return this.http.get('/api/controls', {
    params: { userId },
    withCredentials: true // 关键配置:携带Cookie
  });
}

方式二:全局拦截器统一配置

如果不想每个请求都写一遍,可以用HTTP拦截器全局设置:

// 新建拦截器文件 credential.interceptor.ts
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable()
export class CredentialInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    // 克隆请求并添加withCredentials配置
    const authenticatedReq = req.clone({ withCredentials: true });
    return next.handle(authenticatedReq);
  }
}

然后在AppModule里注册这个拦截器:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { CredentialInterceptor } from './credential.interceptor';

@NgModule({
  providers: [
    { 
      provide: HTTP_INTERCEPTORS, 
      useClass: CredentialInterceptor, 
      multi: true // 允许多个拦截器共存
    }
  ]
})
export class AppModule {}

2. 配置Spring允许跨域携带凭证

如果你的Angular和Spring不在同一域名/端口,必须在Spring里配置CORS,明确允许携带凭证,并且指定允许的前端来源(不能用*,浏览器不允许通配符搭配凭证)。

方式一:Controller级别的CORS配置

直接在你的接口Controller上添加@CrossOrigin注解:

import org.springframework.web.bind.annotation.CrossOrigin;

// 替换成你实际的Angular地址
@CrossOrigin(origins = "http://localhost:4200", allowCredentials = "true")
@RequestMapping(value ="/controls" , method= RequestMethod.GET) 
@ResponseBody 
public List<InputBase> onLoadResponse(
    @RequestParam (value = "userId") String inputParam,
    HttpServletRequest httpServletRequest,
    HttpServletResponse httpServletResponse, 
    HttpSession session
) { 
    super.responseHeader(httpServletRequest, httpServletResponse); 
    session.setAttribute("root", "root"); 
    return controlService.getControls(...);
}

方式二:全局CORS配置

如果有多个接口需要跨域,推荐全局配置:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        
        // 允许携带凭证
        config.setAllowCredentials(true);
        // 指定允许的前端域名(多个的话用addAllowedOrigin逐个添加)
        config.addAllowedOrigin("http://localhost:4200");
        // 允许所有请求头
        config.addAllowedHeader("*");
        // 允许所有HTTP方法
        config.addAllowedMethod("*");
        
        // 对所有接口生效
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

3. 验证配置是否生效

用浏览器的开发者工具(F12 → Network标签)检查请求:

  • 第一次请求后,响应头里应该有Set-Cookie: JSESSIONID=xxx; Path=/; HttpOnly
  • 后续请求的Request头里应该有Cookie: JSESSIONID=xxx

如果能看到这两个头,说明Session已经能正常保持了,你存在session.setAttribute("root", "root")的数据也能在后续请求中获取到。

三、额外注意事项

  • 不要在Spring里配置server.servlet.session.stateless=true,这会禁用Session,直接导致会话无法保持。
  • 如果你的Spring应用部署在HTTPS环境下,确保Cookie的Secure属性正确配置(浏览器只会在HTTPS请求中携带Secure Cookie)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:15:19