Angular 5调用Spring REST接口无法生成服务端Session问题求助
我之前也碰到过一模一样的跨域Session问题,核心根源其实是浏览器的跨域安全策略默认会阻止Cookie在跨域请求中传递——而Spring的Session正是依赖JSESSIONID Cookie来跟踪会话的。本地开发时Angular跑在4200端口、Spring在8080端口,属于跨域场景,所以哪怕接口调用成功,Cookie也没传递到后端,Spring自然生成不了Session;但打包部署到Tomcat后,两者同属一个域名(localhost:8080),浏览器自动携带Cookie,Session就正常工作了。
下面是具体的解决方案,分Angular端和Spring端两步配置:
Angular端配置:允许请求携带Credentials
在HTTP请求中开启
withCredentials
每次调用Spring接口时,需要在HttpClient的请求选项里设置withCredentials: true,这样浏览器才会在跨域请求中携带Cookie。比如你的登录请求可以改成这样:import { HttpClient } from '@angular/common/http'; // ... constructor(private http: HttpClient) {} login(email: string, password: string) { return this.http.post( '/MacromWeb/ws/login', // 用代理的话写相对路径即可 { email, password }, { withCredentials: true } // 关键配置,必须加 ); }代理配置中同步开启Credentials
如果已经用了Angular代理,要在proxy.conf.json里加上withCredentials: true,确保代理层会把Cookie传递到后端:{ "/MacromWeb/ws/*": { "target": "http://localhost:8080", "secure": false, "changeOrigin": true, "withCredentials": true // 新增这一行 } }启动Angular时记得指定代理配置:
ng serve --proxy-config proxy.conf.json
Spring端配置:允许CORS携带Credentials
Spring的CORS默认不允许携带Credentials,必须显式配置,而且不能用*作为允许的Origin(浏览器禁止带Credentials的请求使用通配符Origin)。
方案1:接口级配置(用@CrossOrigin注解)
在你的登录接口所在的Controller上添加注解,指定允许的Origin并开启Credentials:
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @CrossOrigin(origins = "http://localhost:4200", allowCredentials = "true") @RestController @RequestMapping("/ws") public class LoginController { @PostMapping("/login") public String login(@RequestBody LoginRequest loginRequest, HttpServletRequest request) { // 强制创建Session(如果之前不存在的话) HttpSession session = request.getSession(true); System.out.println("生成的Session ID: " + session.getId()); // 处理登录逻辑... return "登录成功"; } }
方案2:全局CORS配置
如果多个接口都需要跨域,可以配置全局CORS规则,避免逐个接口加注解:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class GlobalCorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/ws/**") // 匹配你的接口路径 .allowedOrigins("http://localhost:4200") // 允许的Angular地址 .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方法 .allowCredentials(true); // 允许携带Credentials } }
验证Session是否生成
可以在Spring的登录接口里打印Session ID,控制台能输出ID就说明配置生效了。
至于为什么打包部署到Tomcat就正常?因为此时Angular的静态资源和Spring接口都在http://localhost:8080域名下,属于同域请求,浏览器会自动携带JSESSIONID Cookie,Spring就能正常跟踪会话了。
内容的提问来源于stack exchange,提问作者Bhavin

