满足下面其中一个条件即要跨域:
- 协议不同
- 域名不同
- 端口不同
跨域的方式我总结了以下几种:
第一种:window.name
和<iframe>
标签实现跨域
<iframe>
标签的src
能跨域;window.name
属性值在文档刷新后依旧存在
使用
window.name的值是字符串形式,最大可2M。 服务器端:
//第一种php的代码
echo '<script> window.name = "{"name":"xiaobai", "age":100}" </script>';
我没有采用php的,而是用node.js起了一个服务器,监听了90端口。 代码如下:
var http=require("http");
http.createServer(function(req,res){
res.writeHead(200,{'Content-Type':'text/html'});
res.end("<script>window.name='{"name":"xiaobai", "age":100}'</script>");
}).listen(90);
将要返回的数据转化为字符串,赋值给window.name
(是在JavaScript代码中)
客户端的: 注意:如果index.html页面和和该页面里的iframe
框架的src
如果不同源,则也无法操作框架里的任何东西,也就取不到iframe
框架的name
值了。所以要将iframe
再链接到与index.html同源的页面,才能获取它的window.name
值。
<script>
function cross(url, fn) {
var iframe = document.createElement("iframe");
iframe.style.display = "none";
var flag = 0;
if(iframe.addEventListener){
iframe.addEventListener("load", loadfn)
}else if(iframe.attachEvent){
iframe.attachEvent("onload", loadfn)
}else{
iframe.onload= loadfn;
}
iframe.src = url;
document.body.appendChild(iframe);
function loadfn(){
if (flag==0) {
flag = 1;
iframe.contentWindow.location.href = "about:blank";
} else {
fn(iframe.contentWindow.name);
iframe.contentWindow.close();
document.body.removeChild(iframe);
}
}
}
function fn(data) {
if(typeof JSON == 'undefined'){
//为了兼容IE6 IE7 IE8(Q) 不支持 JSON 对象。
var script=document.createElement("script");
script.src="json2.js";//json2.js文件可以在网上下载
document.body.appendChild(script);
}
data = JSON.parse(data);
console.log(data);
}
cross("http://127.0.0.1:90/", fn);
</script>
完成!
第二种:JSONP跨域
JSONP的最基本的原理是:动态添加一个<script>
标签,而<script>
标签的src
属性是没有跨域的限制的。 网上摘录的:
简述原理与过程:首先在客户端注册一个callback, 然后把callback的名字传给服务器。此时,服务器先生成 json 数据。 然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp。最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析<script>
标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里。(动态执行回调函数)
使用:
服务端代码:
//第一种php的代码
$jsonp = $_GET["callback"];
$str = $jsonp .'({name: xiaobai, age: 100})';
echo $str;
这里我同样才用的是node.js的代码
代码如下:
var http=require("http");
var url = require("url");
http.createServer(function(req,res){
var params = url.parse(req.url, true).query;
res.writeHead(200,{'Content-Type':'text/html'});
var obj={
name:"xiaobai",
age:100
}
res.end(params.callback+"('"+JSON.stringify(obj)+"')");
}).listen(90);
客户端代码:
<script>
if(typeof JSON == 'undefined'){
var script=document.createElement("script");
script.src="json2.js";
document.body.appendChild(script);
}
function cross(url, fn) {
var url=url+"?callback=fn";
var script=document.createElement("script");
script.src=url;
document.body.appendChild(script);
}
function fn(data) {
data = JSON.parse(data);
console.log(data);
}
cross("http://127.0.0.1:90", fn);
</script>
完成!
第三种:html5的postMessage()跨域
window.postMessage
是一个安全的跨源通信的方法 otherWindow.postMessage(message, targetOrigin);
otherWindow是窗口引用,message将要发送到其他 window的数据,targetOrigin通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*
"(表示无限制)或者一个URI。这个大家可以去查一下api.
- message事件 调函数第一个参数接收 Event 对象,有三个常用属性:
- data:消息
- origin:消息来源地址
- source:发送消息的窗口对象
使用:
服务端:
var http=require("http");
http.createServer(function(req,res){
res.writeHead(200,{'Content-Type':'text/html'});
var obj={
name:"xiaobai",
age:100
}
obj=JSON.stringify(obj);
res.end("<script>window.onmessage=function(e){ if(e.source!=window.parent) return; window.parent.postMessage('"+obj+"','*');}</script>");
}).listen(90)
客户端:
<script>
if(typeof JSON == 'undefined'){
var script=document.createElement("script");
script.src="json2.js";
document.body.appendChild(script);
}
function cross(url, fn) {
var iframe=document.createElement("iframe");
iframe.style.display="none";
iframe.src=url;
document.body.appendChild(iframe);
iframe.onload= function () {
iframe.contentWindow.postMessage('getData','http://127.0.0.1:90');
window.onmessage=function(e){
fn(e.data);
}
}
}
function fn(data) {
data = JSON.parse(data);
console.log(data);
}
cross("http://127.0.0.1:90", fn);
</script>
完成!
第四种:CORS(跨域资源共享)
CORS是XMLHttpRequest Level 2 里规定的一种跨域方式。在支持这个方式的浏览器里,javascript的写法和不跨域的ajax写法一模一样,只要服务器需要设置Access-Control-Allow-Origin: *
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
使用
服务端:
var http=require("http");
http.createServer(function(req,res){
var options={
'Content-Type':'text/html',
'Access-Control-Allow-Origin':'http://localhost',//该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
'Access-Control-Allow-Credentials':false,//该字段可选。它的值是一个布尔值,表示是否允许发送Cookie
'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,OPTIONS',//各种请求方式
'Access-Control-Allow-Headers':'X-Custom-Header'//该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段
}
res.writeHead(200,options);
var obj={
name:"xiaobai",
age:100
}
obj=JSON.stringify(obj);
res.end(obj);
}).listen(90)
客户端:
<script>
if(typeof JSON == 'undefined'){
var script=document.createElement("script");
script.src="json2.js";
document.body.appendChild(script);
}
function cross(url, fn) {
var xhr = createCORSRequest('GET', url);
xhr.onload = function() {
var responseText = xhr.responseText;
fn(responseText);
};
xhr.onerror = function() {
console.log('There was an error!');
};
xhr.setRequestHeader('X-Custom-Header', 'value');//自定义头部字段
xhr.send(null);
}
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
//xhr.withCredentials = true;//不对cookies做任何事情,既不发送也不改变.服务端在处理这一请求时,也需要将Access-Control-Allow-Credentials设置为true
// "withCredentials"属性是XMLHTTPRequest2中独有的
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
//IE
// 检测是否XDomainRequest可用
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// CORS不被支持
xhr = null;
}
return xhr;
}
function fn(data) {
data = JSON.parse(data);
console.log(data);
}
cross("http://127.0.0.1:90", fn);
</script>
完成!