We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
不论是开放的API接口,还是部署在不同服务器的项目,很多都绕不开跨域这个问题,那么跨域有哪些常见的解决方案呢?
jsonp主要依赖script标签的src属性可以实现跨域访问,在请求的url后拼上相应的回调函数字段,后端也需要对返回的数据外包一层函数名进行处理。
script
src
jsonp由两部分组成:回调函数和传入的数据,很重要的一点:jsonp 只支持 GET 方法,不支持POST
这里以豆瓣的API为例,实现一个跨域请求。url为:https://api.douban.com/v2/book/search?q=JavaScript高级程序设计&count=2
url中q表示查询图书时输入的信息,count表示查询结果的条目数。这里以查询JavaScript高级程序设计为例,结果为2条。
<script type="text/javascript"> //定义自己的回调函数 function handleResponse(data){ console.log(data); } </script> <!-- 将自己的回调函数拼在url后的callback中 --> <script type="text/javascript" src="https://api.douban.com/v2/book/search?q=JavaScript高级程序设计&count=2&callback=handleResponse"></script>
通过这样的方法,将传入数据拼在url后,将自己的回调函数拼在url的callback中,再在回调函数中对获取到的数据进行处理,就实现了发起跨域请求。
callback
这里设置一个button,点击后动态获取数据,代码如下:
<script type="text/javascript"> function handleResponse(data){ console.log(data.books[1]); } </script> <script type="text/javascript"> window.onload = function() { var btn = document.getElementById('btn'); btn.onclick = function() { var script = document.createElement('script'); script.src = 'https://api.douban.com/v2/book/search?q=JavaScript高级程序设计&count=2&callback=handleResponse'; document.body.appendChild(script); } } </script>
点击后可以看到成功获取到了数据:
$.ajax({ type: "get", url: "https://api.douban.com/v2/book/search?q=JavaScript高级程序设计&count=2", dataType: "jsonp", // 将返回的数据类型设置为jsonp方式 jsonp: "callback", //请求php的参数名 jsonpCallback: "handleResponse", //要执行的回调函数 success: function(data) { console.log(data); } });
这里会先调用指定的 handleResponse ,然后再调用 success。其中 handleResponse 是随着参数传入的回调函数,success是该请求成功发送成功时一定会调用的回调函数,怎么使用就看你怎么写了。
handleResponse
使用$.getJSON()调用如下:
$.getJSON()
$.getJSON("https://api.douban.com/v2/book/search?q=JavaScript高级程序设计&count=2&callback=?", function(data){ console.log(data); });
将url作为第一个参数传入,其中令callback=?,将回调函数作为第二个参数传入,这样也可实现跨域,会得到和前面一样的请求结果。
callback=?
jsonp
CORS全称是“跨域资源共享”,允许向跨域服务器发送Ajax请求。对于开发者来说,和使用Ajax没有什么区别,关键在于服务器,只要服务器实现了CORS的支持,就能实现跨域访问。关于CORS的兼容性如下:
CORS
可以看到绝大多数浏览器都支持CORS,而IE则必须在IE10及以上。IE10以下的则使用的是XDomainRequest对象,这里就不展开了。
IE10
XDomainRequest
CORS请求可以分为简单请求和非简单请求两种,浏览器对这两种请求的处理方式有所不同。
若请求满足以下所有条件,则该请求视为“简单请求”:
使用以下方法之一:
GET
POST
HEAD
HTTP首部不得设置以下集合之外的字段:
Accept
Accept-Language
Content-Language
Content-Type
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type 的值仅限于下列三者之一:
text/plain
multipart/form-data
application/x-www-form-urlencoded
对于简单请求,浏览器会直接发送CORS请求,在请求报文的头部信息中自动添加一个Origin字段,表示发起请求的源。例如:
Origin
Origin: http://foo.example
而服务端返回的响应首部中则有Access-Control-Allow-Origin字段:
Access-Control-Allow-Origin
Access-Control-Allow-Origin: http://foo.example
表示允许域名为http://foo.example的外域向自己发起跨域的CORS请求,如果想让任意域名都能发起请求,可以将它的值设置为*
http://foo.example
*
如果是非简单请求,那么在发起CORS请求前,必须使用OPTIONS方法发起一个预检请求。该预检请求中也会自动添加一个Origin字段表示请求源,还会携带以下两个字段:
OPTIONS
Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER
分别表示此次请求使用的方法和额外的自定义请求首部(若有多个则用逗号隔开)。如果服务器通过了预检请求,那么返回的响应首部中会有如下几个字段:
Access-Control-Allow-Origin: http://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type Access-Control-Max-Age: 86400
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Max-Age
关于CORS更为详细的介绍可以参考:
在存在iframe的页面中,要想发起跨域访问,可以采用降域或者postMessage的方式实现。
iframe
降域
postMessage
降域的前提是二者的主域名要一致,例如a.example.com和b.example.com。在当前页面和iframe源页面均需要设置document.domain属性才能实现降域,这样二者可以跨域访问:
a.example.com
b.example.com
document.domain
document.domain = "example.com";
包含iframe的页面中还可以使用postMessage进行消息传递来进行跨域访问。
<!-- index.html 父页面 --> <h1>this is index</h1> <iframe src="./iframe.html" id="myiframe"></iframe>
<!-- iframe.html 子页面 --> <h1>this is iframe</h1>
这里有两个不同源的页面index.html和其中包含的iframe的源页面iframe.html。
index.html
iframe.html
//index.js var myiframe = document.getElementById('myiframe'); myiframe.onload = function () { myiframe.contentWindow.postMessage('data from index', '*'); }
首先获取iframe元素,然后当它加载完成后向它发送一条消息,这里的contentWindow表示获取的iframe页面的window对象,postMessage方法挂载在window对象上。
contentWindow
window
postMessage方法接受的第一个参数是发送的数据,可以是任何原始类型的数据。第二个参数表示发送到的url,这里设置为*表示所有url都允许。还有更高级的第三个可选参数,这里就不展开了。
url
//iframe.js window.onmessage = function (event) { console.log(event.data); }
然后在iframe页面中监听message事件即可,event.data即为发送的数据。
message
event.data
//iframe.js parent.postMessage('data from iframe', '*')
在iframe的源页面中,直接使用parent关键字即可获得父页面的window对象,然后调用postMessage发送数据。
parent
//index.js window.onmessage = function (event) { console.log(event.data); }
同样的,在父页面中监听message事件来捕获子页面的消息传递。
参考:
The text was updated successfully, but these errors were encountered:
No branches or pull requests
不论是开放的API接口,还是部署在不同服务器的项目,很多都绕不开跨域这个问题,那么跨域有哪些常见的解决方案呢?
jsonp
jsonp主要依赖
script
标签的src
属性可以实现跨域访问,在请求的url后拼上相应的回调函数字段,后端也需要对返回的数据外包一层函数名进行处理。如何使用
jsonp由两部分组成:回调函数和传入的数据,很重要的一点:jsonp 只支持
GET 方法,不支持POST
这里以豆瓣的API为例,实现一个跨域请求。url为:https://api.douban.com/v2/book/search?q=JavaScript高级程序设计&count=2
url中q表示查询图书时输入的信息,count表示查询结果的条目数。这里以查询JavaScript高级程序设计为例,结果为2条。
通过这样的方法,将传入数据拼在url后,将自己的回调函数拼在url的
callback
中,再在回调函数中对获取到的数据进行处理,就实现了发起跨域请求。动态获取
这里设置一个button,点击后动态获取数据,代码如下:
点击后可以看到成功获取到了数据:
jQuery中使用 jsonp
这里会先调用指定的
handleResponse
,然后再调用 success。其中handleResponse
是随着参数传入的回调函数,success是该请求成功发送成功时一定会调用的回调函数,怎么使用就看你怎么写了。使用
$.getJSON()
调用如下:将url作为第一个参数传入,其中令
callback=?
,将回调函数作为第二个参数传入,这样也可实现跨域,会得到和前面一样的请求结果。jsonp
的局限性CORS
CORS
全称是“跨域资源共享”,允许向跨域服务器发送Ajax请求。对于开发者来说,和使用Ajax没有什么区别,关键在于服务器,只要服务器实现了CORS
的支持,就能实现跨域访问。关于CORS
的兼容性如下:可以看到绝大多数浏览器都支持
CORS
,而IE则必须在IE10
及以上。IE10
以下的则使用的是XDomainRequest
对象,这里就不展开了。CORS
请求可以分为简单请求和非简单请求两种,浏览器对这两种请求的处理方式有所不同。简单请求
若请求满足以下所有条件,则该请求视为“简单请求”:
使用以下方法之一:
GET
POST
HEAD
HTTP首部不得设置以下集合之外的字段:
Accept
Accept-Language
Content-Language
Content-Type
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type 的值仅限于下列三者之一:
text/plain
multipart/form-data
application/x-www-form-urlencoded
对于简单请求,浏览器会直接发送
CORS
请求,在请求报文的头部信息中自动添加一个Origin
字段,表示发起请求的源。例如:而服务端返回的响应首部中则有
Access-Control-Allow-Origin
字段:表示允许域名为
http://foo.example
的外域向自己发起跨域的CORS
请求,如果想让任意域名都能发起请求,可以将它的值设置为*
非简单请求
如果是非简单请求,那么在发起
CORS
请求前,必须使用OPTIONS
方法发起一个预检请求。该预检请求中也会自动添加一个
Origin
字段表示请求源,还会携带以下两个字段:分别表示此次请求使用的方法和额外的自定义请求首部(若有多个则用逗号隔开)。
如果服务器通过了预检请求,那么返回的响应首部中会有如下几个字段:
Access-Control-Allow-Origin
与简单请求中的一致。Access-Control-Allow-Methods
表示服务端允许客户端发起请求时使用的所有方法。Access-Control-Allow-Headers
表示客户端发起请求时允许携带的请求首部。Access-Control-Max-Age
则表示预检请求过期的时间,单位为秒,这里是86400秒,也就是24小时。关于CORS更为详细的介绍可以参考:
iframe
在存在
iframe
的页面中,要想发起跨域访问,可以采用降域
或者postMessage
的方式实现。iframe 降域
降域的前提是二者的主域名要一致,例如
a.example.com
和b.example.com
。在当前页面和iframe
源页面均需要设置document.domain
属性才能实现降域,这样二者可以跨域访问:postMessage
包含
iframe
的页面中还可以使用postMessage
进行消息传递来进行跨域访问。这里有两个不同源的页面
index.html
和其中包含的iframe
的源页面iframe.html
。父页面向子页面发送消息
首先获取
iframe
元素,然后当它加载完成后向它发送一条消息,这里的contentWindow
表示获取的iframe
页面的window
对象,postMessage
方法挂载在window
对象上。postMessage
方法接受的第一个参数是发送的数据,可以是任何原始类型的数据。第二个参数表示发送到的url
,这里设置为*
表示所有url
都允许。还有更高级的第三个可选参数,这里就不展开了。然后在
iframe
页面中监听message
事件即可,event.data
即为发送的数据。子页面向父页面发送消息
在
iframe
的源页面中,直接使用parent
关键字即可获得父页面的window
对象,然后调用postMessage
发送数据。同样的,在父页面中监听
message
事件来捕获子页面的消息传递。参考:
The text was updated successfully, but these errors were encountered: