资讯专栏INFORMATION COLUMN

js中跨域的方法

Jacendfeng / 3417人阅读

摘要:但是这种方法适用于和窗口,和无法通过这种方法规避同源策略。逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。

在制作oneday-music-player的时候要使用ajax向百度音乐的api发送请求,然后出现了XMLHttpRequest cannot load "http://...." . No "Access-Control-Allow-Origin" header is present on the request resource. Origin "http://...." is therefore not allowed access,经过搜索发现是受到了同源策略的影响而导致的跨域问题,所以学习一下关于跨域的知识点。

同源策略

同源策略限制从一个源加载的文档或脚本与另一个源的文档或脚本进行交互的方式,是隔离潜在恶意文件的重要安全机制。

两个页面拥有同样的协议、端口(如果指定)和域名时,可以说两个页面是同源的。

下表是相对于http://store.company.com/dir/page.html同源检测的示例:

url 结果 原因
http://store.company.com/dir2/other.html 成功
http://store.company.com/dir/inner/other.html 成功
https://store.company.com/secure.html 失败 不同协议(httpshttp
http://store.company.com:81/dir/etc.html 失败 不同端口(81和80)
http://news.company.com/dir/other.html 失败 不同域名(newsstore

而如果非同源,则有三种行为会受到限制:

Cookie、LocalStorage和IndexDB无法读取

DOM无法获得

AJAX请求不能发送

规避同源策略(跨域) Cookie document.domain

Cookie是服务器写入浏览器的一小段信息,只有同院的网页才能共享。但是,两个网页一级域名相同,只是二级域名不同,浏览器允许通过document.domain共享Cookie

例如,假设文档中的一个脚本在http://store.company.com/dir/page.html执行以下语句:

document.domain = "company.com"

此时,http://news.company.com/dir/other.htmlhttp://store.company.com/dir/other.html
就可以通过document.cookie来设置或获取Cookie,即共享Cookie。

但是这种方法适用于Cookie和iframe窗口,LocalStorage和IndexDB无法通过这种方法规避同源策略。

iframe

如果两个网页不同源,就无法拿到对方的DOM,典型的例子是iframe窗口和window.open方法打开的窗口,如果和父窗口不同源,则会报错。

此时如果两个窗口一级域名相同,只是二级域名不同,那么设置document.domain属性,就可以规避同源策略。

而对于完全不同源的网站,目前有三种方法可以解决跨域窗口之间的通信问题。

片段标识符(fragment identifier)

window.name

跨文档通信API(cross-document messaging)

片段标识符

片段标识符(fragment identifier)指的是URL的#后面的部分,即http://store.company.com/dir/other.html#fragment#fragment(location.hash),如果只改变片段标识符,页面不会重新刷新。

父窗口可以把信息写入子窗口的片段标识符,子窗口通过监听hashchange事件得到通知。

window.name

每个iframe都有包裹它的window,这个window是top window的子窗户,所以自然有window.name属性,指的是当前窗口的名字,这个属性的最大特点是,无论是否同源,只要在同一个窗口里,窗口内所有页面对window.name都有读写的权限。

window.name的值只能是字符串的形式,这个字符串的最大能允许2M左右甚至更大的一个容量,具体取决于不同的浏览器。

例如,想要在http://example/a.html中获取http://company.com/data.html中的数据,可以在a.html中使用一个隐藏的iframe,将iframe的src首先设置为http://company.com/data.html,将其window.name设置为所需的数据内容,随后再将这个iframe的src设置为跟a.html页面同一个域的一个页面,不然a.html获取不到该iframe的window.name

window.postMessage

这是html5中新引入的一个API,可以使用它向其它的window对象发送消息,无论这个window对象属于同源还是不同源。

例如,父窗口http://example/a.html向子窗口http://company.com/data.html发送消息:

var newWin = window.open("http://company.com/data.html", "title")
newWin.postMessage("Hello World!". "http://company.com/data.html")

window.postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源,即协议+端口+域名,也可以设置为*,表示不限制域名。

子窗口向父窗口发送消息的写法类似:

window.opener.postMessage("Nice to see you", "http://example/a.html")

子窗口和父窗口都可以通过message时间,监听对方的消息。

window.addEventListener("message", function(e) {
    // ...
}, false)

message事件的事件对象event有以下三个属性:

event.source: 发送消息的窗口

event.origin: 消息发向的网址(可以限制目标网址)

event.data: 消息内容

通过window.postMessage,也可以读写其他窗口的localStorage

AJAX

同源策略规定,AJAX请求只能发给同源的网址,否则就报错,但是有三种方法可以规避这个限定:

JSONP

WebSocket

CORS

JSONP

JSONP是服务器与客户端跨源通信的常用方法。基本思想是利用

阅读需要支付1元查看
<