跨域

只要协议、域名、端口有任何一个不同,都被当作是不同的域。对于端口和协议的不同,只能通过后台来解决。

 协议:http    主域名:cnblogs.com    子域名:www         端口号: 2050

CORS(跨域资源共享)

         原理:使用自定义的HTTP头部让浏览器与服务器进行沟通

并不是所有的浏览器都支持

Node.js中的应用

//allow custom header and CORS

app.all('*',function (req, res, next) {

 res.header('Access-Control-Allow-Origin', '*');    //设置允许的域

 res.header('Access-Control-Allow-Headers', 'Content-Type,Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');//允许的header类型

 res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE,OPTIONS');

  if (req.method == 'OPTIONS'){

    res.send(200); /让options请求快速返回/

  }

  else {

    next();

  }

});

JSONP

     原理: 网络上javascript的请求不存在跨域限制,动态插入script标签

     优点:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;

它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;

在请求完毕后可以通过调用callback的方式回传结果。

缺点:只能实现get请求,不能实现post请求;(单域操作)

它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

服务端

//通过require将http库包含到程序中

var http = require('http');

//引入url模块解析url字符串

var url = require('url');

//引入querystring模块处理query字符串

var querystring = require('querystring');

//创建新的HTTP服务器

var server = http.createServer();

//通过request事件来响应request请求

server.on('request',function(req, res){

   var urlPath = url.parse(req.url).pathname;

   var qs = querystring.parse(req.url.split('?')[1]);

   if(urlPath === '/jsonp' && qs.callback){       //先判断是不是jsonp请求,如果是就把请求头设置为json

       res.writeHead(200,{'Content-Type':'application/json;charset=utf-8'});

       var data = {

           "name": "Monkey"

       };

       data = JSON.stringify(data);

       var callback = qs.callback+'('+data+');';

       res.end(callback);

   }

   else{

       res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'}); //否则请求不变

       res.end('Hell World\n');   

   }   

});

//监听8080端口

server.listen('8080');

//用于提示我们服务器启动成功

console.log('Server running!');

前端页面

<!DOCTYPE html>

   <head>

       <title>jsonp</title>

       <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>

   </head>

   <body>

       <script>

           function test(data){

               alert(data.name);

           };

       </script>

       <scriptsrc="http://127.0.0.1:8080/json?callback=test"></script> //在请求的地址拼接json和回调函数的名称

   </body>

</html>

通过修改document.domain+ifame来跨子域

对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain= ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!代码如下:

www.a.com上的a.html

document.domain = 'a.com';

var ifr = document.createElement('iframe');

ifr.src = 'http://script.a.com/b.html';

ifr.style.display = 'none';

document.body.appendChild(ifr);

ifr.onload = function(){

   var doc = ifr.contentDocument || ifr.contentWindow.document;

    // 在这里操纵b.html

   alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);

};

script.a.com上的b.html

document.domain = 'a.com';

这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。

备注:某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。

问题:

    1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。

    2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。但是不同的框架之间(父子或同辈),是能够获取到彼此的window对象的。

只要把http://www.example.com/a.html 和 http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。注意:只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,

window.name

www.a.com/c1.html

www.a.com/代理.html

www.b.com/c2.html 下写入数据window.name = ‘数据a’

在c2下创建一个c1的代理文件,与c2共用数据。请求c1.html时可以通过代理。

         优点: 既不复杂,也能兼容到几乎所有浏览器,安全

利用iframe和location.hash

<iframe src= “xxx.b.com#key1=value1&key2=value2”></iframe>

更新a页面的hash值:parent.location.hash =

IE和chrome不支持

在a.com中添加一个页面,设置parent.location.hash =;然后再设置parent.location.hash =self.location.hash;

HTML5中新引进的window.postMessage

适用于跨子域

在 HTML5 规范中,除了 XDM 部分之外的其他部分也会提到这个方法名,但都是为了同一个目的:向另一个地方传递数据。对于 XDM 而言,“另一个地方”指的是包含在当前页面中的<iframe>元素,或者由当前页面弹出的窗口。

postMessage()方法接收两个参数:一条消息和一个表示消息接收方来自哪个域的字符串。第二个参数对保障安全通信非常重要,可以防止浏览器把消息发送到不安全的地方。来看下面的例子。

//注意:所有支持 XDM 的浏览器也支持iframe 的 contentWindow 属性

var iframeWindow =document.getElementById("myframe").contentWindow;

iframeWindow.postMessage("Asecret", "http://www.wrox.com");

最后一行代码尝试向内嵌框架中发送一条消息,并指定框架中的文档必须来源于"http://www.wrox.com"域。如果来源匹配,消息会传递到内嵌框架中;否则, postMessage()什么也不做。这一限制可以避免窗口中的位置在你不知情的情况下发生改变。如果传给 postMessage()的第二个参数是"*",则表示可以把消息发送给来自任何域的文档,但我们不推荐这样做。

接收到 XDM 消息时,会触发 window 对象的 message 事件。这个事件是以异步形式触发的,因此从发送消息到接收消息(触发接收窗口的 message 事件)可能要经过一段时间的延迟。触发 message事件后,传递给 onmessage 处理程序的事件对象包含以下三方面的重要信息。
q data:作为 postMessage()第一个参数传入的字符串数据。
q origin:发送消息的文档所在的域,例如"http://www.wrox.com"。

q source:发送消息的文档的 window 对象的代理。这个代理对象主要用于在发送上一条消息的
窗口中调用 postMessage()方法。如果发送消息的窗口来自同一个域,那这个对象就是window。

接收到消息后验证发送窗口的来源是至关重要的。就像给 postMessage()方法指定第二个参数,
以确保浏览器不会把消息发送给未知页面一样,在 onmessage 处理程序中检测消息来源可以确保传入
的消息来自已知的页面。基本的检测模式如下。
EventUtil.addHandler(window,"message", function(event){
//确保发送消息的域是已知的域
if(event.origin == "http://www.wrox.com"){
//处理接收到的数据
processMessage(event.data);
//可选:向来源窗口发送回执
event.source.postMessage("Received!","http://p2p.wrox.com");
}
});

用jQuery的ajax解决跨域问题的简单版:

 jQuery.ajax()支持get方式的跨域,这其实是采用jsonp的方式来完成的。

            $.ajax({ 
            async:false, 
            url:'http://www.mysite.com/demo.do',  // 跨域URL
            type:'GET', 
            dataType:'jsonp', 
            jsonp:'jsoncallback', //默认callback
            data:mydata, 
            timeout:5000, 
            beforeSend:function(){  //jsonp 方式此方法不被触发。原因可能是dataType如果指定为jsonp的话,就已经不是ajax事件了
            },
            success:function (json) { //客户端jquery预先定义好的callback函数,成功获取跨域服务器上的json数据后,会动态执行这个callback函数 
                if(json.actionErrors.length!=0){ 
                    alert(json.actionErrors); 
                } 
                genDynamicContent(qsData,type,json); 
            }, 
            complete:function(XMLHttpRequest, textStatus){ 
                $.unblockUI({fadeOut: 10 }); 
            }, 
            error:function(xhr){ 
                //jsonp方式此方法不被触发
                //请求出错处理 
                alert("请求出错(请检查相关度网络状况.)"); 
            } 
        });

       $.getJSON("http://www.mysite.com/demo.do?name1="+value1+"&callback=?", 
            function(json){ 
                if(json.属性名==值){ 
                    //执行代码 
                } 
        }); 
    这种方式其实是上例$.ajax({..}) api的一种高级封装,有些$.ajax api底层的参数就被封装而不可见了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值