为了解决跨域请求无法使用cookie的问题,使用nginx对后端服务做了反代。但是反代之后,却发现cookie没有被正确传递。

相关配置

nginx 反代配置

nginx反代的配置很简单,只是简单设置了proxy_pass

1
2
3
location /edims-api {
    proxy_pass http://server_ip:port/;
}

Spring Boot后端服务配置

后端服务使用内嵌Tomcat,且设置了context-path。

1
2
3
4
server:
  # 省略了无关配置
  servlet:
    context-path: /path

分析

打个比方,登录请求需要请求两个接口A和B。在A接口中,会往session中存入一些数据,在访问B接口的时候需要从session中取出A接口存入的数据。在使用了nginx反代了后端服务之后,请求B接口时,无法从session中取到需要的数据,原因在于访问B接口时,浏览器没有自动将cookie带上,所以每次访问接口的session都不一样。

一般来说,后端在Response Header中设置Set-Cookie之后,浏览器在向服务器发起其他请求时,自动带上设置的cookie,如果没有带上,那就只能说明,肯定是第二次请求接口时,有什么条件不符合导致浏览器没有自动带上cookie。

参考MDN上的资料(参考 MDN-Cookies

The Domain and Path directives define the scope of the cookie: what URLs the cookies should be sent to.

浏览器根据cookie的domain和path,决定为哪些url请求发送cookie,而根据我的nginx配置来看,domain肯定是一致的,区别就在于path了。

首先看一下cookie的path: -w669

再来看一下请求url的path: -w553

原因找到了,因为后端设置的cookie的path与反代之后访问地址的path不一致,才导致浏览器在B接口请求时并没有发送该cookie。

解决

修改nginx的反代配置,在location中添加proxy_cookie_path

1
2
3
4
location /edims-api {
    proxy_pass          http://server_ip:port/;
    proxy_cookie_path   /edims-background /edims-api/edims-background;
}

总结

一般来说,我们的Java后端应用并不会设置context-path,那默认的cookie的path其实应该是 /,这样的话,也就不会发现反代还会导致cookie丢失这种情况了。不过如果碰到了,只要了解web开发相关的基础知识,也还是很好解决的。