JavaScriptweb前端饥人谷技术博客

跨域

2017-02-28  本文已影响51人  IT男的成长记录

1.什么是同源策略

2.什么是跨域?跨域有几种实现形式

3.JSONP的原理是什么?

function addScriptTag(src){
    var script = document.createElement('script');
    script.src = src; //跨域网址
    document.body.appendChild(script);  
    // 往页面插入元素后,会向跨域网址发出请求(src指定了跨域网址,得到响应后立即执行
}

window.onload = function(){
    addScriptTag("http://example.com/ip?callback = foo');  //当页面加载完毕,即往页面中插入script元素
}

function foo(data){
    console.log('your public ip address is: '+ data.ip)'
}

2.上面代码通过动态添加<script>元素,向服务器example.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字,这对于JSONP是必需的。
3.服务器收到该请求后,会将数据放在回到函数的参数位置返回

foo({
  "ip": "8.8.8.8"
});

4.由于<script>元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,因此避免了使用JSON.parse的步骤。

4.CORS是什么?

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

在上面的头信息中,Origin字段表明了本次请求来自哪个源:协议、域名、端口。

2.该请求到达服务器后,服务器会根据这个值来判断是否接受请求。如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段(如下所示)。如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

3.浏览器收到响应后判断该相应头中是否包含Origin的值,如果响应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获,这时我们无法拿到响应数据。如果有则浏览器会处理响应,我们就可以拿到响应数据。

5.降域

// A网页和B网页设置相同的document.domain
document.domain = 'example.com'
// A网页通过脚本设置Cookie
document.cookie = "test1 = hello";
// B网页可以获取到该cookie
var otherCookie = document.cookie;
A 网页
URL: http://a.yanxin.com:8080/a.html
<div class="ct">
  <h1>使用降域实现跨域</h1>
  <div class="main">
    <input type="text" placeholder="http://a.yanxin.cn:8080/a.html">
  </div>
  <iframe src="http://b.yanxin.com:8080/b.html" frameborder="0" ></iframe>
</div>

<script>

document.querySelector('.main input').addEventListener('input', function(){
  console.log(this.value);
  /* window.frames 是窗口中所有命名的框架组成的数组。
  这个数组的每个元素都是一个Window对象,对应于窗口中的一个框架。
  window.frames[0]得到的就是html中的框架
  window.frames[0].document.querySelector('input') 得到框架中的input元素
  */
  window.frames[0].document.querySelector('input').value = this.value;
})

document.domain = "yanxin.com"
</script>
iframe中的B网页
URL: http://b.yanxin.com:8080/b.html
<input id="input" type="text"  placeholder="http://b.yanxin.com:8080/b.html">
<script>

document.querySelector('#input').addEventListener('input', function(){
    // 得到父窗口中的input元素
    window.parent.document.querySelector('input').value = this.value;
})
document.domain = 'yanxin.com';
</script>

6.postMessage

页面A:  http://a.yanxin.cn:8080/a.html
在页面A中打开页面B: http://b.yanxin.cn:8080/b.html
当点击页面A上的button时,向页面B传输消息"hello world"
  <button id="sendmessage">send message</button>
  <script>
   var button = document.querySelector("#sendmessage");
  // 打开页面b,并且取得对它的引用
   var targetWindow = window.open("http://b.yanxin.cn:8080/b.html");
   button.addEventListener('click',function(){
   // 注意: 这里是向targetWindow即新打开的窗口(通过上面的window.open打开的窗口)发送消息
  // 直接打开页面b(手动打开的)是无法收到消息的
  // 如果直接调用postMessage则相当于当前窗口向自己发送消息
      targetWindow.postMessage("hello world!!", "http://b.yanxin.cn:8080/b.html");
   });
   
  </script>
为页面B的window添加监听器
当页面B收到Message时,在控制台中输出收到的消息,并提示"hello"
<script>
    window.addEventListener("message", receiveMessage);
    function receiveMessage(event){
        console.log(event.data);
        alert("hello");
    }
</script>

参考资料:

CORS 详解-阮一峰
浏览器同源政策及其规避方法-阮一峰
Window.postMessage() - Web APIs | MDN

上一篇下一篇

猜你喜欢

热点阅读