Appearance
前言
最近在公司碰到了内嵌的iframe始终提示未登录的问题,查询到时接口请求时未自动携带cookie,排查过程中一直没搞懂cookie携带的机制。将排查后学习到总计一下。
问题
先来几个问题
- cookie是怎么设置到浏览器中,设置cookie有什么限制
- 什么样的请求能携带cookie,能携带哪些cookie
- cookie存储方式是什么
- cookie 和 storeage 区别
- 跨域和跨站
跨域和跨站
同域: 协议、域名、端口相同,反之是跨域
同站: eTLD + 1, 顶级域名 + 1 相同则是同站,反之是跨站
请求的场景
假设当前网站是xunserver.cn, 页面地址是http://cloud.xunserver.cn/file。这个页面发出的请求有以下几种
- 同域请求,http://cloud.xunserver.cn/patha
- 跨域请求不跨站 https://cloud.xunserver.cn/patha 和 http://cloud.xunserver.cn:8088/patha
- 子域名请求 http://nps.cloud.xunserver.cn/patha
- 跨域同时跨站 http://docker.xunserver.com/patha
- 上级域名请求 http://xunserver.cn
cookie
cookie组成
cookie 包括name, value, domain, path, expire, httpOnly, secure, samesite。
cookie 如何被设置
有两种设置cookie的方法
- 请求响应头中set-cookie
- 前端JS代码document.cookie。
通过响应设置cookie时, domian默认是当前请求的eTLD + 1, 路径默认是/。可以设置上级域名和上级路径的cookie,如果设置子域名或者子路径,cookie设置会无效,而且会被抛弃。
document.cookie 设置和set cookie类似,前者被限制于当前文档的地址(浏览器地址栏),而且不能设置httpOnly和secure 属性。
cookie 如何被携带
当浏览器发送请求时,根据请求的场景携带cookie不同。
- 同域请求, 自动携带当前请求所有的子域名和父路径, 会携带path=/patha、path=/ 和 domain=cloud.xunserver.cn、xunserver.cn的cookie
- cookie不区分端口和协议,所以同上一致
- 会携带domain=nps.cloud.xunserver.cn 以及上级域名
- 携带domian=docker.xunserver.cn
- 携带domain=xunsrever.cn 不会携带cloud.xunserver.cn 域名
samesite 是啥
用户在银行登录了系统,这个时候浏览器嵌入了cookie,如果恶意网站中有一个form表单,提交地址是银行的链接,用户在点击链接后就会触发接口,因为请求携带了cookie,所以银行会判断为正常用户,从而带来不安全。或者恶意网站嵌套i银行frame,诱导用户点击,实际点击到了银行网站的接口。 samesite有三个值,strict, lax 和none
strict 表示只有请求在同站的情况下,才会携带cookie。
lax 表示除了a标签、预加载、get表单能cookie外,其余场景都不能携带,包括iframe
none 表示不限制
samesite 如何设置,浏览器默认是lax, 匿名浏览器如果关闭第三方共享是strict。如果设置none,需要同时secure,同时在https下设置
跨域如何携带cookie
哪些些请求能跨域
link、img、script 标签支持跨域,但是new Image不支持。跨域能发送请求,但是不能解析响应。 其余的通过axios或者fetch发送跨域请求, axios 需要添加withCredentials: true支持跨域携带cookie
fetch 需要添加withCredentials: include属性
fetch withCredentials解析
omit 跨域不打送cookie include 总是发送 same-origin 同站才发送
storage
localstorage 和 sessionStorage 严格按照同源原则。
document.domain 用来干嘛
可以把父页面和iframe的domain设置成一个(都需要设置,因为document.domain调用后端口会被设置为null),父页面可以拿到iframe的window对象,从而调用iframe中的方法实现跨域。设置document.domain 仅设置自身或者上级域名,不能设置为其他或者子域名。
也可以通过window.open 获取引用
如何检查浏览器同时打开多个相同页面
循环检查localStorage
host、referer和origin
host: 指向请求的host和端口号,任何请求都有
referer: 当前请求发起的来源,一个页面跳转到另一个页面指向的是之前的页面,页面内发起的资源请求,指向当前文档的地址,不包含hash origin: 跨域请求中常见 ,指向原始
