黑马程序员技术交流社区

标题: 【上海校区】一文读懂 CORS 跨域 [打印本页]

作者: LittlePrince    时间: 2020-3-19 15:09
标题: 【上海校区】一文读懂 CORS 跨域
前端开发经常会遇到跨域问题,通过搜索基本都能解决,或者直接交给后端处理,只要浏览器不要再报下面的错误就行。
XMLHttpRequest cannot load api.example.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access.
在解决这个问题后,我还是感觉云里雾里,阅读了很多资料,最终认为自己“理解”了,以下是我的理解内容:
浏览器为了用户数据安全,默认不允许跨域。只要 XMLHttpRequest 发起请求的源和浏览器地址栏中的源不一致,请求就会被限制。解决办法是采用跨域资源访问(CORS),后端在 Response Header 中写入 Access-Control-Allow-Origin: * 。
后来又查了一下 Access-Control-Allow-Origin 的作用,发现这个理解有点肤浅。
关于跨域我提出了如下几个问题:
如果对以上问题存在疑惑,希望这篇文章能为你解答。
在讲跨域前,我们需要了解一点基础知识。
HTTP 前瞻浏览器通常是基于 HTTP 协议和 Web 服务器通信的,因为 HTTP 协议无状态的特性,浏览器会在本地存储服务端发来的 Cookie,在下次发送请求时,带上 Cookie 来表明自己的身份,Cookie 就属于用户数据。
为了提高 HTTP 通信的效率,HTTP 设计了缓存策略,用来缓存 Response 数据,下次发起同样的请求时,会尝试使用本地缓存,来加快请求速度,减小服务器压力。
HTTP Respone 中可能会携带用户敏感信息。
浏览器能访问不同的网站,用户数据原本存在各自的远端服务器,但如果用户数据支持本地缓存,就会共处于浏览器缓存中。访问银行网站,会缓存银行卡、手机号等信息;看小电影,会缓存一些小电影的元数据。
这些数据都能被浏览器访问,那如何保证小电影网站的 JS 代码,不会偷偷读取银行网站缓存的用户数据,然后上传到它们后台呢?
同源策略浏览器会对访问本地数据的 JS 进行监管,想要获取本地数据,就需要携带身份信息,默认只允许 JS 访问和它同源的数据,这就是同源策略。
浏览器在存储用户数据时,会标记数据的来源(Origin)。当 JS 脚本访问本地数据时,会检查它的源是否和用户数据关联的源一致,不一致就会拒绝访问。
JS 和 HTML 是同源的,即显示在浏览器地址栏中的 Scheme + Host + (Port)。
A 网站在发起 XMLHttpRequest 请求时,浏览器会在该请求的 Header 中添加 Origin: A 字段,来表明请求者的身份。需要注意这里的 A 并不是 XMLHTTPRequest 的 Host,而是 JS 文件的来源。

">
浏览器会先检查本地是否存在该请求的 Response 缓存,如果存在并且缓存未失效,会验证 JS 的来源,也就是 XMLHttpRequest Header 中的 Origin 字段。
上图中 XMLHttpRequest 请求的源是 http://testdrive.dasouche.net ,如果该请求之前已经发起成功过,本地会存在它的 Response 缓存,并且缓存会有这个源标记。
Request Header 携带的源(Origin)是 http://f2e.su.dasouche.net ,它代表 JS 文件的来源,浏览器检查到它与缓存的源不一致,会拒绝访问 Response,并抛出 XMLHttpRequest 请求异常。
上面的例子,看上去不太合理,如果请求从来没有成功过,就不会存在缓存。
其实如果本地没缓存, XMLHttpRequest 简单请求依然会发出去,并且会把 Response 写入了缓存(如果允许的话),之后浏览器才会根据以上同源策略,控制缓存的读取。
CORS 跨域在实际开发中,请求 HTML/JS 资源的源,可能和 XMLHttpRequest 请求不同源。跨域就是为了突破浏览器同源策略的限制。
JS 想要跨越它的来源限制,去访问 XMLHttpRequest 请求的 Response 数据。所以严格来讲跨域的说法并不准确,准确的说法应该叫跨源。
实现跨域的方法有很多,比如有 JSONP、WebSocket、CORS 等。我们来看看最常见的 CORS 是如何实现跨域的。
CORS 全称跨源资源共享(Cross-Origin Resource Share),也就是通过某种机制来共享数据。
服务端在返回 Response 时,默认只允许同源的 JS 访问,如果服务端在 HTTP Response 中附加一个白名单,标记允许哪些域访问该资源,就允许了跨域访问。
这个白名单就是响应头 Access-Control-Allow-Origin。
浏览器会允许 Access-Control-Allow-Origin 白名单中的域访问 Response,如果是 Access-Control-Allow-Origin: * 就表示允许任何域访问该 Respone,这是存在安全隐患的。
如果恶意网站制造一个和银行网站一模一样的请求,本地 Response 缓存没有访问权限控制,浏览器会傻傻的把响应数据交给这个恶意网站。
所以对于用户数据敏感接口,最好还是不要开启允许任意域访问,而是采用白名单机制。
小结同源策略在浏览器端保证用户数据的安全,但它也给同一个网站不同域请求的数据共享带来不便。
因此就有了跨域的需求,跨域的方法有很多,本文主要介绍了 CORS 跨域,以及它的原理。
虽然同源限制来自于浏览器,但 CORS 允许跨域的开关掌握在服务端。这样即保证了用户数据的安全,又实现了数据的共享,可谓一举两得。


文章转载自:https://juejin.im/post/5e72bd8b51882549165435f1






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2