

同源和跨域的那些事-简单图文总结 - 安木夕
source link: https://www.cnblogs.com/anding/p/17459031.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.


01、为什么要跨域?
跨域的根本原因是浏览器的“同源策略”,得先了解什么是同源?—— 就是【协议+域名+端口号】相同,即为同源,只能向同源的服务发起AJAX请求。

源1 | 源2 | 是否同源 |
---|---|---|
a.com | b.com | 🚫不同源,域名不同 |
http://a.com | https://a.com | 🚫不同源,协议不同 |
a.com:80 | a.com:443 | 🚫不同源,端口不同 |
gg.com | a.gg.com | 🚫不同源,子域名不同 |
a.com/ss | a.com/s2 | 同源 |
可通过
location.origin
、window.origin
获取当前文档的源
❓为什么要同源呢?
这是浏览器故意设计的,是浏览器的基本安全策略,否则会很容易受到XSS、CSRF攻击。只能向同源的服务发起AJAX请求,不可跨域请求,会被浏览器拦截。
❓有哪些限制规则呢?
- ✅ 访问其他源的图片、CSS、JS是可以的,允许
<img src="url">
、<link href="url">
、<script src="url">
元素获取的其他源的资源。 - ✅ Form表单可以跨域提交,表单的提交只是提交数据无需返回,浏览器认为是安全的。
- 🚫 AJAX不可以向其他源发送网络请求,会被浏览器拦截。注意拦截的不是请求,而是响应,服务端依然是可以收到请求的。
- 🚫 仅可访问自己域的cookie、localStorage、DOM树,不能访问Iframe嵌入的其他页面内部内容。

02、如何实现跨域?
随着互联网越来越复杂,需求也越来越多,跨域请求就很常见了。我们知道了跨域是浏览器的同源限制,就可以针对性的想办法了。
2.1、JSONP跨域
这是一种传统的跨域请求办法,借助于<script>
标签元素,因为<script>
的src
可以访问任何站点的资源。当然这需要服务端对应接口支持JSONP(JSON with padding)协议,所以是需要双方约定好,所以浏览器认为这是安全的。
- 优点是兼任IE,实现跨域。
- 缺点是不能控制请求过程,仅支持GET方式请求。因为只是一个
<script>
标签,浏览器自动发起的资源请求。
JSONP(JSON with Padding)是JSON的一种”使用模式“,是一种非官方的协议,用于解决浏览器的跨域数据访问的问题。
📢前端具体实现过程:
- 1、申明一个全局的回调函数“getData”来接收数据。
- 2、动态创建一个
<script>
标签,src
为要跨域的API地址,URL中带上回调参数“callback=getData”。 - 3、服务端收到请求后,动态生成一个脚本,脚本内容是一个字符串,由回调+返回的数据构成:“
getData('data')
”。 - 4、本地执行远程脚本,回调函数“getData”运行,就得到了想要的数据。
<script src="http:www.thrid.com/cors/api?q=key&callback=back"></script><script> function back(data) { console.log(data); }</script>
JSONP的实现:
function jsonp(url, args, cbName) { return new Promise((resolve, reject) => { const ele = document.createElement('script'); window[cbName] = (data) => { resolve(data); document.body.removeChild(ele); } args = { ...args, callback: cbName }; ele.src = `${url}?${Object.keys(args).map(k => `${k}=${args[k]}`).join('&')}`; document.body.appendChild(ele); });}//使用,api为360的公开接口jsonp('https://sug.so.360.cn/suggest', { format: 'jsonp', word: 'china' }, 'search') .then(function (data) { console.log(data) });
2.2、CORS跨域
CORS是什么?—— 跨域资源共享 (cross-origin resource sharing),让AJAX可以跨域访问数据。这是为了满足跨域请求的需求,W3C新增加的特性,需要服务端的支持,不支持IE8/9。根据请求方式,浏览器将CORS分为两种情况:
- 简单请求(安全请求):只支持GET、POST、HEAD,Header只支持部分字段。
- 复杂请求(其他请求):简单请求以外的其他跨域请求。
🔵简单请求
基本原理就是在请求头加入一个身份来源标识,服务端根据这个标识来判等是否允许访问,如果允许则给一个允许的标记并返回响应。
- 只支持GET、POST、HEAD。
- header —— 我们仅能设置基础的安全字段:
- Accept
- Accept-Language
- Content-Language
- Content-Type 的值为 application/x-www-form-urlencoded,multipart/form-data 或 text/plain。
📢具体过程比较简单,前端只要在Header加入“Origin”即可:
- 请求头Header加入要跨域的源:
origin:http://www.main.com
GET /api HTTP/1.1Origin: http://www.main.com //本次请求来自哪个源Host: http://www.third.com //请求的第三方APIAccept-Language: en-USConnection: keep-aliveUser-Agent: Mozilla/5.0...
- 服务端收到请求后检查Origin,如果同意请求则正常响应,同时在响应的Header中加入特殊的“Access-Control-Allow-Origin”字段,申明支持的源,也可以用“*”表示支持任何源访问。
- 浏览器收到响应后会检查“Access-Control-Allow-Origin”,和当前源对比,如果不合法则会报错——跨域。
Access-Control-Allow-Origin: http://www.main.com //请求允许的源Access-Control-Allow-Credentials: true //是否允许cookie,cors默认不发送cookie,如果要发送,还需AJAX中设置withCredentialsAccess-Control-Expose-Headers: Content-Length,API-Key //如果客户端想要访问其他非安全字段,则需要服务端明确定义哪些Header字段暴露出来Content-Type: text/html; charset=utf-8

🟠复杂请求
不是简单请求的都称为复杂请求(非简单请求),如请求方法是PUT、DELETE,或Content-Type=application/json
。相比于简单请求,复杂请求多了一次预请求。
预请求:
- 正式发送请求前,浏览器会自动发送一个预请求,问问服务端是否允许本次请求,如果回应允许才正式发送请求,后面就和简单请求相同了。
- 预请求及其响应都没有body,采用
OPTIONS
方法。

03、跨域小结
因为同源是浏览器的限制,跨域的方法无非就是绕过,或采用CORS。
跨域方案 | 基本原理 | 是否需要服务端支持 |
---|---|---|
JSONP | 借助<script> 标签的src ,加上一个全局回调函数接收数据 |
🟠需要服务端支持JSONP协议 |
CORS | W3C标准支持的跨域方式,请求头添加Origin 字段 |
🟠需要服务端支持 |
WebSocket | WebSocket可以实现浏览器与服务端的双向通信,没有跨域的困惑。推荐第三方库 Socket.io,可以很方便的建立与服务端的Socket通信。 | 🟠需要服务端支持,支持WebSocket |
iframe+postMessage | 使用window.postMessage() 来实现窗口之间的通信 |
🔵不需服务端处理,客户端绕过 |
服务端代理 | 由自己的同源服务端代理第三方的请求 | 🟠需要服务端支持,代理请求 |
nginx反向代理 | 原理和服务端代理一样,用nginx配置一个代理服务 | 🔵不需要服务端修改代码,需nginx支持 |
©️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀
Recommend
-
70
*本文作者:x565178035,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。 同源策略 准确的说,同源策略是指,浏览器内部在发起如下请求时,该来源必须是当前同源的HTTP资源: 1. 以跨站点的方...
-
40
背景 提起这个方案,还要从某个风和日丽的早晨说起。那日小编正忙着手上的各种需求,突然后端的亲火急火燎的找到小编,说是有一个重要的用户,在使用 Word 在线编辑文档功能时,发现保存的文件被篡改了。一听到这,我心想这下...
-
14
什么是同源策略同源策略是指在浏览器中,允许某个网页的脚本访问另一个网页的数据(如Cookie),但前提是这两个网页必须是同源的,同源指的是两个网页协议相同,域名相同,端...
-
5
Nginx解决同源策略跨域 - 搞搞震省略一万字… localtion ~ .*\.(ttf|otf|eot|woff)$ { add_header Access-Control-Allow-Origin *; 或指定域名 add_header Access-Control-Allow-Origin "http://www.example.com"; }
-
5
同源策略引发的跨域问题它都能轻松解决!先来认识认识有这么强大功能框架的神奇之处...
-
6
跨域?如何解决?同源策略? 跨域:
-
4
00、 引言 作为一名IT码农,入行十载有余,写的代...
-
12
01、 健康饮食很重要 1.1、健康...
-
3
JavaScript入门系列目录 01、事件基...
-
5
01、什么是HTTP缓存,如何工作的? 当我们打开一个页面...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK