技术饭

解决两个跨域但是同站、同域、同源的域名(Sec-Fetch-Site: same-site),通过接口请求设置session_id()改变PHPSESSID的问题

copylian    0 评论    2147 浏览    2021.08.14

工具:

前端域名:htps://qd.copylian.com

接口域名:https://api.copylian.com

验证码接口:https://api.copylian.com/index.php/get/verify


现象:

1、两个https的二级域名解析在同一台服务器上,端口都是443

2、前端域名与接口域名同时在同一个浏览器打开,接口域名登录后台生成PHPSESSID,保存了登录状态

1628910500(1).png

3、前端域名请求接口域名生成验证码,验证保存在session里面,由于访问接口,每次的会话session_id都是不一致,为了实现跨域验证码的验证,这个时候需要在接口端设置session_id(随机数),然后把这个随机值返回给前端,到时候验证的时候再设置session_id(随机数),这样会话才能保持一致,验证码才能通过验证

3-1、重新生成session_id

tapd_41997644_base64_1628732745_3.png

3-2、验证验证码设置session_id

tapd_41997644_base64_1628732768_44.png

4、由于步骤3设置session_id(随机数)重新生成PHPSESSID后,导致了步骤2登录后台的PHPSESSID被改成了步骤3设置的PHPSESSID,这时候步骤2的登录状态就消失了,直接退出登录

4-1、前端接口返回一个接口域名根目录的PHPSESSID

1628912256(1).png

4-2、接口域名的PHPSESSID也被改变了

1628912337(1).png


分析:

1、经过多轮测试,发现如果把其中一个https改为http那么请求属性 Sec-Fetch-Site 就变成了 cross-site,这样是没问题的,也就是跨域但不同域、不同站、不同源的话PHPSESSID是没问题的,但是我们的需求必须都是https

2、前端设置请求头 Sec-Fetch-Site:cross-site,但是查看了 SameSite  的介绍以及解析,发现Sec-开头的是被保护的无法直接设置

3、网上很多资料说是通过后端头或者配置修改 SameSite  的值,但是php7.2.24暂时没有SameSite配置,php7.3以上版本才有此项配置,网上给出的php7.2版本及一下的配置方法是:header('Set-Cookie: cross-site-cookie=name; SameSite=None; Secure'); 但是配置之后还是无效果

4、尝试把接口端域名生成的PHPSESSID保存到redis里面,然后再取出来重新设置这个PHPSESSID值,这样设置似乎看起来没问题,但是每个浏览器无法确定唯一性,所以也作罢

5、最后发现:既然PHPSESSID能被跨域请求修改,但是跨域请求有获取不到PHPSESSID的值,而且PHPSESSID的cookie存的path是根目录 / ,当时猜想如果我重新生成的PHPSESSID把存储目录做修改是否就能解决问题呢!果然!答案是肯定的,直接将session的path目录改成 /tmp,当然这个目录必须存在切可写,不过这也是一个折中的办法,暂时我也没找到更好的法子

1628921615(1).png

参考资料:

同站 和 同源 你理解清楚了么?

PHP Cookie SameSite 的設定方式

Cookie 的 SameSite 属性

PHP的 SameSite 属性配置

Sec-Fetch-Site

飓风呀
感谢你的支持,我会继续努力!
扫码打赏,感谢您的支持!

文明上网理性发言!

  • 还没有评论,沙发等你来抢