最近在学习 CORS 同源策略问题,看到几个观点:
1 、跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是响应结果被浏览器拦截了。 不仅仅是静态的资源。WebStorage 、Cookie 、IndexDB ,在浏览器层面上都是以域这一概念来划分管理的。 而且这个划分管理行为,就是在浏览器本地生效。和服务器、其他客户端没有直接关系。
2 、当响应的是附带身份凭证的请求时,服务端必须明确 Access-Control-Allow-Origin 的值,而不能使用通配符。
针对 1 ,比如说我做为可能有恶意脚本的黑客,不管你请求头带不带 origin ,我返回的 js 响应报文中,我始终带上 "Access-Control-Allow-Origin: *
"这个响应头啊。 这样我的恶意 js 不就可以被浏览器解释并执行了?
针对 2 ,这个服务端必须是为什么要必须明确呢?如果不明确会怎么样呢? CORS 做为一个浏览器对资源请求的约束,它咋知道我的请求带不带身份呢?
请教各位大佬赐教一下
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Guides/CORS
![]() |
1
lululau 6 天前
我理解所谓「同源策略」是用来防止 CSRF 的而不是 XSS 的吧
|
2
FlyaiF PRO 应该是为了防止浏览器里边进行一些假冒的网站,引导用户做一些用户意料外的操作吧
|
3
hurrytospring 6 天前 ![]() 1. 对,但是需要理解安全机制防的是什么,cors 机制中,防范的是跨站脚本攻击,比如在 A 网站中,发起一个对你服务( B )的请求,这个时候就可以携带上 B 的 cookie ,然后在请求中读 B 身份的内容。
至于你说的场景 1.1. 是黑客劫持了响应,然后注入恶意脚本,其实这个时候没有那么麻烦,黑客可以直接劫持 A 的请求。 1.2. 这个场景一般来说是依赖 https 或者更底层的协议来保护,跟 cors 没有关系 2. 身份是一个统一的认证头,key 为 authorization ,如果你就是不用这个 key ,自己设计一个,你就自己越过了这个安全机制,你的服务你自己负责。 2.1 allow:*本质上是一种宽松校验机制,就是如果你认为你这个接口信息不重要,可以让别的站随便拿,你可以定义为*。但是当有这个 header 时,浏览器认为,这不是一个宽松的接口,是含有认证信息的敏感接口,应该采用更严格的校验机制,所以不让你用宽松的配置。 2.2 当然,你可以觉得浏览器说得不对,你换一个认证的 header key ,这个时候浏览器也不对这个事情负责,你可以继续 allow:* ,属于你自己越过安全机制,自己负责 |
4
Y25tIGxpdmlk 6 天前
这好比就是正规浏览器遵守的一个保护用户的规则而已吧。
比如有支付宝和微信 2 个网站,如果你用浏览器访问支付宝网站,支付宝如果很坏,里面嵌入了微信的页面。由于微信页面的跨域限制,支付宝页面是不能获取到他嵌入页面的相关数据的,比如 cookie 之类的。虽然对浏览器来说,2 个网站的数据他都有,但是浏览器会遵守一个约定,微信的页面说不能把内容让支付宝看,那他就会隔离 2 个网站。 相应的,如果微信的页面返回里,允许了支付宝,那他的数据就会被共享给支付宝。说白了还是要看浏览器是不是正规,是不是遵守跨域限制。当然你也可以自己魔改一个浏览器或者客户端,直接不遵守跨域限制。 |
5
Y25tIGxpdmlk 6 天前
其实你的这类问题,问 ai 是非常好用的,你各种不理解,可以一点点的问他,他会给你讲的非常到位
|
![]() |
6
bronyakaka 6 天前
一个和 cors 无关,自己信任了外部输入并执行,毕竟传过来的本来只是 js 字符串而已;第二个是 csrf
|
7
chinafengzhao OP 问过了,并不到位,甚至会乱回答。
|
8
cppc 6 天前
1 简单请求是浏览器直接发出,收到服务器响应后拦截
2 非简单请求是先发预检请求,检查服务端响应头,然后根据规则再发实际请求(也就是说可能不会发出真实请求) |
![]() |
9
AoEiuV020JP 6 天前
cros 是保护用户自己的,入户用户自己是黑客不需要保护,cros 没用的,
比如你作为用户可以安装一个插件“Allow CORS”,就能绕过 cors 的限制,我有时候用一些 web app 会这样,等于允许这个 web app 爬取其他网站的数据, 如果用户不是黑客的话,中间人是靠 https 防范的, |
![]() |
10
wangtian2020 6 天前
跨域是后端问题,后端问题
禁止是浏览器出于安全,浏览器方面自作主张禁止的,默认假设你的 URL 是对的,如果 URL 不带跨域头那就不让页面收到信息 |
![]() |
11
wangtian2020 6 天前
例如,假如没有跨域限制,那我是不是可以做个跟支 F 宝完全一样的页面,只加一行代码把用户名密码发来
那用户一看页面长的一样,页面行为也一样,不知不觉中就被盗了 |
![]() |
12
seekafter 6 天前
1. 是对的吗? 我理解的是浏览器做出的跨域限制. 因为同样的跨域请求, 浏览器提示 cors, api 工具就会成功
2. 如果携带 cookie, 但设置"Access-Control-Allow-Origin: *", 你的 cookie 会自动被浏览器丢弃. 另外如果你有自定义请求头, 还需要设置响应头为 Access-Control-Allow-Headers: cookie,自定义请求头 1, 头 2... 这个的设置要和你的请求头完全一致 另外前端发请求还需要设置一个 inc 开头的属性. 等我博客启动了发你文章参考下 |
13
GeruzoniAnsasu 6 天前
A 域数据被 B 读,你要保护数据,请问是在 A 上设防火墙还是在 B 上?
B 是发起 CORS 请求的站点,现在你理解了不? 如果 A 域数据很敏感,你必然要开个白名单只允许特定 B 来读。除了这个白名单外,你可能希望 A 和 B 上都有一些过滤和拦截,那么浏览器就是 B 上的额外防护层。 你从服务端该怎么响应请求的角度出发会容易理解得多,这也是为什么 CORS 明明只是个很简单的机制但为啥这么多前端一直迷迷糊糊的原因。 |
14
fuzzsh 6 天前 via Android
OWASP 记录了大部分攻击手段和防护措施,可以看下他们的文档
|
![]() |
15
irisdev 6 天前
楼主这算是典型初学者的困惑,很多技术在不知道其背景之前总是会产生类似的疑问,其实大多数技术也只是某些场景好用,很多问题是没办法解决的,或者要在可用性、易用性、通用性和绝对安全之间作取舍
|
16
fruitmonster 6 天前
V2 不知道为什么这么喜欢讨论跨域请求呢? /t/1056504 /t/1056793
|
17
chinafengzhao OP @seekafter 可以出一篇文章详解一下,等你大作。大家都在说跨域是浏览器行为, 这个我的理解是这样的,浏览器是个公共应用,用户打开浏览器可以访问各种各样的域名各种各样的网站。 网站会在客户端存各种各样的数据(比如用户身份登录态(抱歉这是我自己造的一个词),字体偏好等等(比如通过 session,cookie,webstorage 等),可以理解这是针对域名来对这些数据分开隔离的),所谓大家都在说,不允许带 cookie 啥的。 但是忽略了我的原始问题,不同网站的凭证可能是不同方式实现的,是业务自己私密的实现。这个也不属于标准或协议层面。
**当响应的是附带身份凭证的请求时,服务端必须明确 Access-Control-Allow-Origin 的值,而不能使用通配符“*”。** 协议或者说浏览器要求带这个头部之类的,他怎么判断这个是不是普通请求呢?有些请求里面有 cookie 不代表这是带凭证吧。 @GeruzoniAnsasu |
![]() |
18
unco020511 6 天前
1 的前提是你主动同意黑客这么干,或者说你就是黑客. 比如你主动在电脑中设置代理,并主动安装根证书到电脑,这样就你的 proxy 就可以随意修改 https 的请求和响应. 更进一步,你直接将你的电脑权限交给黑客.所以 1 已经超出了浏览器同源政策的范畴了
2 的话你可以理解是一个额外安全要求,附带身份凭证会认为是敏感信息,所以有一个额外的安全规定. 不过现在用户凭证很多都不用 cookie 之类的,你想放到哪都可以,比如额外搞个 header 附带 token. 浏览器是一个 httpClicent,当然知道你发送的请求细节,包括 https 的握手加密等细节都是浏览器去实现的,它自然知道,具体到开发中,就是设置 withCredentials 的值,你设置为 true 就认为你带了 |
19
chinafengzhao OP 以 MDN 为例,站点 https://foo.example 的网页应用想要访问 https://bar.other 的资源。
如果 https://bar.other 的资源持有者想限制他的资源只能通过 https://foo.example 来访问(也就是说,非 https://foo.example 域无法通过跨源访问访问到该资源) 那我做为 bar.other 来说,我可能有两类资源,一类是静态的什么 js 啥的,第二类是 api 接口业务数据啥的 我想保护我自己。 所谓我可能要在一些有认证态(抱歉这是我造的词,不同网站可能不一样)的 http web api 加上响应头限制。 "Access-Control-Allow-Origin: https://foo.example:" 表示只能是 Origin 为 foo 的请求才能接收。 关键是这个响应已经发出去了啊, 我的保护意义何在呢? 所以如果我设置失误了,对于带 cookie 或者说认证状态的请求,我在响应头 "Access-Control-Allow-Origin: *"设置为这样,浏览器反而自动给我加了个保护,响应虽然发出去了, 在浏览器不解析这个响应报文数据。 ? 所以这是君子协定,靠浏览器的机制保护来约束? 可能这些才是我的疑惑,这些头部约束的目的和要解决的问题其实我是明白的,我其实想问它的控制机制和限制, MDN 这一系列不能,只是为了安全考虑,如果我设置了会怎么样他没说,并且还是那句话,不同的网站,带身份凭证的请求各有不同,做为这种跨域约束协定,或者说我用某个头部做为认证,然后不小心设置了 Access-Control-Allow-Origin: * , 客户端怎么判断请求是否带身份凭证呢?怎么判断这个*应该不被接收呢? ``` 在响应附带身份凭证的请求时: 服务器不能将 Access-Control-Allow-Origin 的值设为通配符(*),而应将其设置为特定的域,如:Access-Control-Allow-Origin: https://example.com 。 服务器不能将 Access-Control-Allow-Headers 的值设为通配符(*),而应将其设置为特定标头名称的列表,如:Access-Control-Allow-Headers: X-PINGOTHER, Content-Type 服务器不能将 Access-Control-Allow-Methods 的值设为通配符(*),而应将其设置为特定请求方法名称的列表,如:Access-Control-Allow-Methods: POST, GET 服务器不能将 Access-Control-Expose-Headers 的值设为通配符(*),而应将其设置为特定标头名称的列表,如:Access-Control-Expose-Headers: Content-Encoding, Kuma-Revision 对于附带身份凭证的请求(通常是 Cookie ), 这是因为请求的标头中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“*”,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为 https://example.com ,则请求将成功执行。 另外,响应标头中也携带了 Set-Cookie 字段,尝试对 Cookie 进行修改。如果操作失败,将会抛出异常。 ``` @GeruzoniAnsasu @GeruzoniAnsasu |
20
chinafengzhao OP @unco020511 其实第一个情况,要考虑到类似 jscdn 这种网站到期了被抢注了,这种域名被篡改了之类的,我做为黑客不一定要中间人攻击请求报文或响应报文,我可能攻击了类似 CDN 这种。 比如说我攻破大家都在用的 <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script> 假设这是我的恶意脚本,在这脚本里面去请求我的网站呢。
|
21
chinafengzhao OP @unco020511 是的,你这个第二点说的很对,用户凭证这个东西不是标准,每个网站实现都不一样,所以我才对这个 MDN 里面关于用户凭证对 Access-Control- 各种头部的限制和要求不太理解。 有点疑惑。
|
22
dorothyREN 6 天前
简单请求没有跨域的问题吧
|
23
GeruzoniAnsasu 6 天前
|
![]() |
24
UnluckyNinja 5 天前
假设跨域情景下的三个角色:用户(以及使用的浏览器),用户访问的网站 A ,网站 A 请求的网站 B 。
首先要明确,跨域规则究竟是在防谁,是为了解决什么问题? 用户访问网站 A ,或者用户访问网站 B ,网站与自身的互动都是同源的,被浏览器信任。 用户访问网站 A 时与网站 B 产生互动,用户可能并不知道会涉及网站 B ,网站 B 也不能信任来自其它前端的不可靠输入,这样的互动是浏览器所要阻止的。 所以,跨域规则是在防当前访问的网站 A 的恶意操作,保护用户与网站 B 之间的数据安全。 如果网站 B 允许网站 A 的跨域请求,那么实际上跨域保护的作用已经结束了。 再来看第一个问题, > “我做为可能有恶意脚本的黑客……我的恶意 js……” 这里假定了网站 B 是恶意方,用户访问的网站 A 是正常的,但如果网站 A 都已经请求了恶意 js ,那网站 A 还是清白的吗? OP 在 20L 举了一个 CDN 投毒攻击的例子,但你首先要想到,在 CDN 投毒之前,这一切是正常运作的,网站 A 请求了网站 B 的资源,网站 B 允许网站 A 的跨域请求。 后来其中某一方背叛了信任,虽然是不同源,但这根本不是跨域规则所要解决的问题,也就是需要禁止的跨域资源访问(非法请求访问合法资源),这直接就相当于是注入代码了。 第二个问题, > “它咋知道我的请求带不带身份呢” 你没写过附带身份凭证的前端请求?你不明确附带身份凭证,那浏览器就不会发送附带身份凭证的请求。凭证是由浏览器管理的,你无法在前端代码中修改跨域请求附带的凭证 https://fetch.spec.whatwg.org/#forbidden-request-header > “这个服务端必须是为什么要必须明确呢?如果不明确会怎么样呢? ” 同样地,在跨域的语境下,你要搞清楚哪方是攻击方,哪方是受保护方(响应端、用户是被保护方,请求端是潜在的攻击方)。 不明确就说明后端根本没有考虑到可能有来自不明源的攻击,既然不遵循浏览器的安全规则,浏览器就当你是需要被保护的对象,禁止一切风险行为。 |
![]() |
25
restkhz 5 天前
我不得不说,很多人理解就错了。CORS 出发点不是“为了安全”,而是为了灵活。
很多人说的其实是 SOP ,同源策略。说白了就是分隔不同站点的 cookie ,认证 header ,资源等。 而后又发现其实有时候我们也是需要跨域访问的,比如你前后段分离。但是因为 SOP ,很多事情都做不了。 所以要打一个补丁,但是你总不能破坏 SOP 吧?所以搞了这一堆机制。存在部分安全限制的灵活。 很多人的困惑就是因为直接看了 CORS ,就觉得这莫名其妙。所以楼主你还是从 SOP 看起吧。 而且人们普遍对 web 攻击理解是有问题的。 比如 3 楼,说的“跨站脚本攻击”,实际上就错了。你说的更像是 CSRF 。 你要是说跨站脚本攻击,但是它的发起可以是同源的,这种 CORS 防不了。 你描述的 CSRF 有时候根本不需要响应内容。服务器收到就好。这种 CORS 也防不了。 而后楼主在 20 楼的问题,这是 CSP 可以解决的。你可以在 html 里给调用的 js 直接写上 hash ,浏览器会自动验证 hash 。可以应对投毒。 如果你在乎安全,去看看 CSP ? |
26
chinafengzhao OP @UnluckyNinja > 在跨域的语境下,你要搞清楚哪方是攻击方,哪方是受保护方(响应端、用户是被保护方,请求端是潜在的攻击方)。 这句话很经典,受教了
|