三方cookie的安全策略应对方案
一、什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。
当前页面url | 被请求页面url | 是否跨域 | 原因 |
http://www.test.com/ | http://www.test.com/index.html | 否 | 同源(协议、域名、端口号相同) |
http://www.test.com/ | https://www.test.com/index.html | 跨域 | 协议不同(http/https) |
http://www.test.com/ | http://www.baidu.com/ | 跨域 | 主域名不同(test/baidu) |
http://www.test.com/ | http://blog.test.com/ | 跨域 | 子域名不同(www/blog) |
http://www.test.com:8080/ | http://www.test.com:7001/ | 跨域 | 端口号不同(8080/7001) |
二、为什么会出现跨域问题
出于浏览器的同源策略限制。
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。这个限制,导致无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB,无法接触非同源网页的 DOM,无法向非同源地址发送 AJAX 请求。
三、什么是三方cookie
如果浏览器存储的cookie的域(domain)和地址栏中的url属于同源,则认为这种cookie为一方cookie,否则为三方cookie(跨域,即非同源网页的 Cookie)。 以下面访问tmall主页为例,浏览器被种下的cookie中,域值为*.tmall.com的cookie为一方cookie(绿色),其他皆为三方cookie(红色)。
三方cookie通常用来用作用户行为追踪、单一登陆等作用。
当A网站通过某种形式访问了B网站的内容或资源(例如img,iframe)时往往会带来三方cookie。
通过三方cookie虽然能实现一些便捷功能(例如多域名登陆,天猫vs淘宝等)但是三方cookie的滥用也会带来诸如CSRF,个人信息泄露等安全问题或风险。
四. 在观远的应用场景里哪些地方用到了三方cookie
主要是两个场景:
-
观远系统以 sso + iframe的形式嵌入到客户的宿主系统中,此时观远为内容提供方,观远的cookie相对于宿主系统来说为三方cookie。
-
观远自己系统中的 iframe内容,例如 iframe外链卡片,润乾填报等。此时润乾或 iframe 外链卡片URL指向的网站为内容供应方,他们提供的cookie相对于观远来说是三方cookie。
五. Chrome 安全策略升级带来的影响
早期Chrome并没有对三方cookie做任何安全管控。从56版本开始提供了一个cookie属性samesite,用来约束三方cookie的行为,并提供了三个选项:
-
Strict: 仅限于同站请求
-
Lax: 同站请求,或者跨站的GET的会导致页面URL发生变化的导航行为,包括链接、GET的Form提交。比如在 http://www.def.com 网站的页面中嵌入了一个链接 http://www.abc.com ,那么在用户点击此链接时发起的初始请求,会带上 http://www.abc.com中设置为Lax的Cookie。而那些设置为Strict的Cookie是不会带上的。这种跨站链接还包括像嵌入到邮件中的链接。
-
None: 没有限制,同站及跨站请求中都会带上,与传统的方式一样。
从76版本开始,Chrome开始升级samesite的默认值,从none变为了Lax。其行为可归纳为:
所以对于2-a, 2-b中的场景,如果内容提供方没有配置更宽松的samesite安全等级(none),该cookie会被Chrome过滤掉。对于2-a来说,我们的uIdToken存储在cookie中,前端无法获取uIdtoken会认为用户没有登录而转向登录页。
其他浏览器
-
Safari 已经完全禁止了三方 cookie (待确认)
-
FireFox,Edge也会陆续跟随 Chrome的行为。
另外对于Chrome,不排除未来会完全禁止三方cookie的可能。
解决方案
根据前面相关问题的描述,我们认为可以提供以下方案给我们的用户:
方案A:
建议用户将观远和他们的业务系统部署在同一个域名下。这是最推荐的方式。
方案B:
在configuration.json中打开开关,我们会同时使用header解决token的传递问题,需要注意,这种方式会降低token的安全性。
"CROSS_SITE_HEADER_TOKEN_ENABLED": true,