浏览器为什么选择了如今的同源策略

2022-03-26 17:48:16 +08:00
 wheelg

浏览器会禁止下面的类似操作

a.com中的 js 向b.com/api发送了请求,根据同源策略,这样的跨域请求会向b.com 发送一个 OPTIONS 预检请求,如果服务器返回的 Access-Allow-Origins 中不包含a.com ,那么此次请求会被浏览器拒绝,a.com中的 js 拿不到请求返回的数据。

这样的行为如果发生在本地应用程序例如 postman 中时,是可以拿到正常的请求数据的,因为 postman 没有同源策略,不会限制发送任何请求,那么为什么浏览器要对此做出限制?

网上的大部分解释是,浏览器在向某个域名发起请求时,会携带上对应的网站 cookie ,如果用户登录了b.com,又打开了a.coma.comb.com/api发送的请求会带上b.com的 cookie ,会让b.com服务器认为是用户本人在操作,导致恶意攻击的发生。

那么为什么浏览器不能分辨是哪个网站发起的请求呢?为什么浏览器不能在检测到是a.com发出的请求时,不携带b.com网站保存的 cookie 呢?这样不就能同样规避此类攻击吗?就如同在浏览器直接输入 api 网址那样拿到返回结果不行吗?

我的理解是,浏览器厂商不能这样做,因为许多广告厂商需要在网站中嵌入第三方 cookie ,这样才能通过第三方 cookie 来确定同一用户,方便广告投放,但是这个说法也显然站不住脚,因为如今许多浏览器厂商都在主动禁止第三方 cookie ,那么这个同源策略到底保护的是什么呢?

7701 次点击
所在节点    程序员
72 条回复
musi
2022-03-26 20:46:28 +08:00
@rekulas #14 你对同源策略似乎有误解,同源策略分为两部分,一部分是发送,一部分是接受。像 get 这类是简单请求,只限制了接受,并没有限制发送,但是这不是说同源策略就不生效。假如服务器用 get 去做了什么转账之类的操作,那服务器收到请求后该怎么执行怎么执行。至于为什么会对 get 的发送进行放行,rfc2616 中定义 get 操作是安全的。
thinkershare
2022-03-26 20:53:40 +08:00
@hazardous 这的确是一个重要考量, 简单资源的盗链目前就在不能修改源的情况下只能使用 iframe, 另外 OP 说的为什么浏览器不能判断是你随意引用别人的内容, 别人也很容易攻击你, 信任是双方的! 我引用的第三方内容在被动态加载到本地化, 在未来完全可能通过修改 DOM, 然后诱导用户输入保密信息, 然后将信息提交到一个第三方从而欺骗你的网站用户, 让网站用户以为是 A 网站自身的行为,. 网页浏览器的普通用户并没有那么高的判断能力!
musi
2022-03-26 21:21:27 +08:00
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS#%E9%A2%84%E6%A3%80%E8%AF%B7%E6%B1%82

和上面两篇结合起来看效果更佳。
这里做下总结:浏览器不能直接禁止 a 网站在访问 b 网站时去掉 b 网站的所有会话信息,因为这违背了 web 的开放性。试想一下:如果现在所有网站只能访问自己的域名的话 web 还是现在的 web 么。那不能禁止怎么办?那就只能定一套协议把控制权交给网站所有者了。
BeautifulSoap
2022-03-26 21:43:45 +08:00
(那么为什么浏览器不能分辨是哪个网站发起的请求呢?为什么浏览器不能在检测到是 a.com 发出的请求时,不携带 b.com 网站保存的 cookie 呢?)


LZ 你难道不知道 js 是可以获取到当前网站的 cookie 的吗。黑客想办法在目标网页内插入了一段 js ,没有同源策略的话这段 js 可以直接获取到用户 cookie 然后直接发给给黑客的服务器(这里说的发送是构造 xhr 请求把 cookie 当参数或 post 之类的请求体发出去)
lscho
2022-03-26 21:58:17 +08:00
"那么这个同源策略到底保护的是什么呢?"

同源策略保护的是当某个站点存在 xss 漏洞、csrf 漏洞时,其他站点不会被影响。

“那么为什么浏览器不能分辨是哪个网站发起的请求呢?为什么浏览器不能在检测到是 a.com 发出的请求时,不携带 b.com 网站保存的 cookie 呢?”

可以,但是浏览器不能代替网站服务提供商做出决定。跨域请求时是否携带 cookie 、以及是否响应的、响应哪些请求权利要交给网站服务提供商来决定。所以这就是如今的同源策略。

以上是我的理解。
wheelg
2022-03-26 22:08:44 +08:00
@BeautifulSoap 目前的同源策略无法防止你说的这种情况哦,如果黑客已经在你的网站里插入了恶意代码,他完全可以直接访问他自己的服务器,只需要用 cors 跨域就可以了。
cxtrinityy
2022-03-26 22:09:18 +08:00
浏览器可以分辨是哪个网站发起的请求, 不然 header orgin 字段没法填吧.
不允许跨域请求带 cookie, 这属于一刀切了吧, 有些网站是允许跨域请求那怎么办, 比如社交网站, 第三方网站添加分享链接, follow 之类的或其他的某些功能需要识别身份的 cookie 呢
CORS 可以保护 CSRF,但 CSRF 也可以用 CSRF token 来处理, 但某个允许跨域请求的网站在跨域时没有 CSRF token , 那 CORS 不就有用了么
保证一个网站无法读取另一个网站的本地数据就安全这个说法有错, CSRF 并不需要恶意网站读取你的 cookie, 而是浏览器读取 cookie, cookie 对于恶意网站即使是黑盒也是可以的, 恶意网站加载时就可以发起跨域请求, 因为虽然是跨域, 但是对于浏览器来说只是发起了一个对目标网站的请求, 如果该请求的 url 符合 cookie 的发送范围, 那 cookie 就会被带上, 假设该 cookie 是用于身份验证, 恶意网站的目的只是借此通过验证, 而不是偷窃 cookie, 接下来完成验证后的操作才是 CSRF 的目的
wheelg
2022-03-26 22:11:16 +08:00
@lscho 第二个解释里,浏览器如果不能代替网站提供商做决定的话,就更不需要如此严厉的同源策略才对,应该把这些东西都交给 js 去控制,这不是更好吗?
jiangzm
2022-03-26 22:12:21 +08:00
同源策略就是设置一个方法可以阻止非预期的请求,但是又允许非同源之间的可访问性。

浏览器当然能知道是哪个网站发起的请求所以自动会带上 referer 方便服务端检测

浏览器不能简单粗暴的直接禁止跨域携带 cookie ,这个选择权得交给客户端,因为太多网站应用需要相互访问

同源策略保护谁就是第一句话提到的,阻止非预期的请求,你用 postman 或者浏览器 get 请求这还属于预期请求当然不用禁止, 那什么是非预期的请求,比如我在我的个人网站 A 嵌入很多 B 网站的请求,互联网用户访问我的 A 网站时发起的 B 网站请求这就属于非预期的请求,B 网站默认只允许 B1 、B2 跨域访问,浏览器预检后就直接禁止了,假设开发粗心设置了允许所有域名跨域访问,也没有做拦截同时访问的又是敏感接口不就有安全问题了吗
wheelg
2022-03-26 22:23:14 +08:00
@jiangzm 换个角度想想,为什么操作系统没有对本地应用程序设置类似同源策略的限制,目前的 web 应用已经基本上可以做到和本地应用一样的登录认证逻辑了吧,那为什么浏览器要格外严格呢?
如果我在我的应用程序代码里也嵌入了很多其他网站的请求,这是不是也属于非预期请求呢?浏览器对网页如此严格的限制看起来还是有其他的原因在
lscho
2022-03-26 22:32:50 +08:00
@wheelg 交给 js 是不可能的。因为 xss 漏洞就是可以插入 js 啊。对于 http 请求说,前端的任何东西都是不安全的。必须有服务器参与这个策略才行。
wheelg
2022-03-26 22:32:59 +08:00
各位可以换个角度想想这个问题,为什么浏览器对网页的限制要比操作系统对本地应用的限制要多得多?

理论上来说,本地应用能获取到的信息、对用户系统的危害远大于网页,为什么反而是浏览器的安全措施更严格(特指网络请求方面)?仅仅是因为本地应用需要下载安装这个步骤比较麻烦吗?那如果以后应用体积越来越小,例如 App Clip 和安卓快应用这类轻量的应用也需要收到类似同源策略的限制吗?

还是说,因为浏览器本身的历史原因,它无法做到和本地应用一样的安全性,才不得已选择了同源策略这种较为严格的手段呢?
DOLLOR
2022-03-26 22:37:38 +08:00
自家网站只能请求自家接口,不是很天经地义的事情吗?
如何分辨哪些网站是自家,哪些网站是别家呢?当然是看域名了。
但是随着 web 的发展,又渐渐出现了“需要向别家网站请求接口”的需求,所以就有了各种跨域的技术。
跨域需要自家和别家开发者共同协作才能做到,这就杜绝了未经许可就擅自使用别家接口的行为。
pursuer
2022-03-26 22:44:27 +08:00
@wheelg 下载安装默认认为用户知道自己在做什么,或者交给操作系统,比如 IOS 你要发布应用要经过 App Store 审核才行。当然现在浏览器也有了不少像 FileSystem 这样的扩展浏览器边界的 API.
DOLLOR
2022-03-26 22:45:14 +08:00
@wheelg

iOS 的应用沙箱,每个应用都只能访问自己的存储空间;就连 Android 都有 /data/data/youPackageName/空间,这跟 web 的“同源策略”是相似的机制,web 的同源策略其实并不特殊。
Puteulanus
2022-03-26 22:45:30 +08:00
本地应用本来就比网页危险啊,操作系统没对本地应用进行更多限制,所以现在本地应用可以肆无忌惮得扫你其他软件的数据然后上传,加密你的数据勒索,要是本地应用像 iOS 一样隔得死死的,哪儿有这些的操作空间

本地应用哪儿来的跟网页一样的安全性
wheelg
2022-03-26 22:54:06 +08:00
@pursuer 有一定的道理,不知道如果以后添加 pwa 也可以被视为“用户知道自己在做什么”的话,会不会取消一定程度的同源限制,postman pwa 版多好啊
jiangzm
2022-03-26 22:58:35 +08:00
@wheelg 因为浏览器多网站网站访问入口,普通软件不会保存其他域的敏感信息所以没有可比性。 如果能自由访问不同的网站那就是浏览器软件了。浏览器本身和本地应用是一样的,浏览器可以拿到本地机器的信息,但是 js 执行在一个沙盒环境,正常是不可能拿到本机的数据和攻击本机。

假设浏览器环境不同域之间的本地数据完全隔离,那也就不用同源策略了,那这样不同 web 应用之间的请求就不可能携带敏感信息。

所以还是那句话既要可阻止也要保证访问性。
shiganwuguo
2022-03-26 23:01:02 +08:00
安全啊
musi
2022-03-26 23:05:40 +08:00
@wheelg 你这个换角度就很不合理,web 是强依赖于网络的,应用又不是。web 的程序、数据全靠网络触达,且 web 开发者是没有权限对自己的 web 做限制的(没有同源的情况下),但是你作为一个本地应用开发者,能做的限制这不是多了去了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/843069

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX