前几天写了个小项目,本地跑的好好的,部署到服务器上也正常。最近在服务器上跑,出幺蛾子了。程序突然报错,本应该从httpServletRequest.getSession()中写入和读出的,但是却读不出,结果为null。开启远程调式,发现程序确实读取不到httpServletRequest.getSession()中的值。
会到本地计算机重新跑程序,程序正常,debug发现同样的值在本地跑可以获取到。
以为是打包jar出问题了,就重新编译打包,并且现在本地计算机上运行jar包。同样显示正常,再次部署到服务器。见鬼了,服务器还是不行,程序读取不到session中的值。既然本地的jar可以正常运行,那么jar打包应该正确。session是依靠cookie的,会不会是跨域的问题?
但是程序中已经标注了allowCredentials = “true”,在前端代码中也设置了xhrFields:{withCredentials:true}要求携带cookie发送请求。
查看程序在本地时cookie情况:
第一次响应是返回cookie的,tomcat的sessionID叫JSESSIONID。
第二次请求携带了cookie。
查看程序在服务器上的运行:
第一次请求没有Cookie
第一次请求服务器同样返回Cookie
但是在随后的请求中,浏览器并没有将服务器给的Cookie携带发送。和第一次请求一摸一样。问题找到了,浏览器没有发送Cookie,导致随后的操作,服务器不知道之前的状态,读取不到对应的参数。导致报错。
问题分析:但是相同的代码,同样的浏览器,为社么在本地计算机就可以发送Cookie,但是在云服务器上就不发送。这里就和后端代码和前端没有关系了,一定是浏览器本身的设置问题。
原来是从Chrome51开始,增加了SameSite属性。详细请看SameSite
简单的说就是SameSite属性,分为3类。Strict、Lax和None。以前发送Cookie是服务器设置allowCredentials:true以及前端代码中设置withCredentials:true。但是现在即使都设置了,SameSite不对也不会发送。
1、Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。
2、Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外
3、Chrome 计划将Lax变为默认设置。这时,网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效
解决办法就是设置成None模式,这样Cookie通过Https发送。
在Microsoft Edge中打开属性,在目标(T)后面增加
--disable-features=SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure
即可。注意是在”“外面加哦。