其他分享
首页 > 其他分享> > 跨源通信

跨源通信

作者:互联网

跨源通信的几种方式 1.JSONP 2.iframe*** 3.window.postMessage() 4.XMLHttpRequest level 2

跨源限制
在浏览器里
对源(url协议,主机名,端口号)不同的通信进行限制,在web领域 为了确保安全,只有同源的通信才能被允许进行,称为同源策略
虽然可以在html里使用iframe以实现在一个页面中同时显示来自不同域的文档,不过js仍然只能访问同一源的文档
如果文档的url和iframe的不同,则无法通过文档中包含的js对iframe内的dom进行操作,而iframe内的js也无法操作文档里的dom
如果不这样 ,就会发生诸如不同域的cookie能够互相访问等安全问题

对于XMLHttpRequest来说,同源策略的含义是,一个XMLHttpRequest对象只能发送至一个特定的服务器,即提供了使用该XMLHttpRequest对象的文档下载服务器
跨源通信

 

js里的跨源通信
JSONP
iframe***
window.postMessage()
XMLHttpRequest level 2

1.JSONP
利用script标签的src将其它域的js文件载入,如果在此处动态创建script标签的话,就能实现对其它域中数据的动态读取
不过仅仅是取得了数据,还无法在客户端使用。因此产生jsonp(json with padding ,padding指向json数据中添加函数名)
服务端会对数据添加函数名后返回
代码示例

 

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>title>
    <script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js">script>head><body><script>var url="http://b.cn/do.php?callback=foo";//注意 foo函数的定义要先于 引入 url里的内容function foo(res){
    console.log(res);
    console.log(res.a);
}function loadData(url){    var elem=document.createElement('script');
    elem.src=url;
    document.getElementsByTagName('head')[0].appendChild(elem);

}
loadData(url);script>body>html>

b.cn/do.php

<?php$arr=['a'=>'ajax','b'=>'bbc'];$callback=$_GET['callback'];$json=$callback."(".json_encode($arr).");";echo $json;   //foo({"a":"ajax","b":"bbc"});?>

请求的内容是执行代码的内容,在客户端是定义声明部分
jsonp的缺点
无法在post请求类型中使用
只能做到动态创建script标签并读取数据而无法从客户端发出数据

2. XMLHttpRequest level 2
XMLHttpRequest无法跨源通信
在XMLHttpRequest level2中 只要服务器端许可就可以实现

a.cn/a.html

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>title>
    <script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js">script>head><body><div class="btn" style="cursor: pointer;text-align:center;width: 100px;height: 50px;line-height:50px;color:white;background: green">clickdiv><script>$(function(){
    $(".btn").click(function(){        var xhr=new XMLHttpRequest();
        xhr.onreadystatechange=function(){            var state=xhr.readyState;            if(state==4){
                console.log(xhr.getAllResponseHeaders());
            }
        }
        xhr.open('GET','http://b.cn/do.php?a=1&b=2');
        xhr.withCredentials=true; 
        //默认不发送cookie的,当设个参数设置为true服务端 Access-Control-Allow-Origin 必须明确指定 不可为* 而且必须设置 header('Access-Control-Allow-Credentials:true');        xhr.setRequestHeader("content-type",'multipart/form-data');//      xhr.setRequestHeader("content-type",'application/x-www-form-urlencoded');        xhr.send('p1=1');

    });

});script>body>html>
http://b.cn/do.php
代码
<?phpheader('Access-Control-Allow-Origin:http://a.cn');header('Access-Control-Allow-Credentials:true');header('Access-Control-Allow-Methods:POST');var_dump($_POST);var_dump($_GET);var_dump(file_get_contents("php://input"));var_dump($_COOKIE);

 关于跨源发送cookie 

xhr.withCredentials=true; 

这里跨源指的是 跨的二级的域,根域必须相同,而且cookie的域必须是根域 

比如 a.a.cn可以通过这里所说的跨源 在向b.a.cn发送ajax请求时 带上 .a.cn下的cookie

不要以为 域在.a.cn下的cookie ,a.a.cn在向b.a.cn发请求时 会自动带上

也不要认为cookie的跨源能跨根域,是不可能的


3.postMessage()

window.postMessage 是一个安全的跨源通信的方法。一般情况下,当且仅当执行脚本的页面使用相同的协议(通常都是 http)、相同的端口(http默认使用80端口)和相同的 host(两个页面的document.domain 的值相同)时,才允许不同页面上的脚本互相访问。 window.postMessage 提供了一个可控的机制来安全地绕过这一限制,当其在正确使用的情况下。


调用 window.postMessage时,将分发一个MessageEvent事件到目标窗口, 在所有挂起必须执行的脚本完成后.  (例如:当一个事件处理程序调用window.postMessage时,仍剩余事件处理程序,  先前的挂起等待超时等)。MessageEvent 有消息类型,它被设置为第一个参数值提供给window.postMessage的data属性, 对应的window调用window.postMessage的时候,window.postMessage主文档的来源的origin属性被称为源属性,指哪个调用window.postMessage的窗口。 (事件的其他标准属性都存在与对应的预期值。)


语法

otherWindow.postMessage(message, targetOrigin);

a.cn/a.html
<!DOCTYPE html><html><head>
    <title>Post Messagetitle>head><body><div style="width:200px; float:left; margin-right:200px;border:solid 1px #333;">
    <div id="color">Frame Colordiv>div><div>
    <iframe id="child" src="http://b.cn/b.html">iframe>div><script type="text/javascript">
    window.onload=function(){
        window.frames[0].postMessage('getcolor','http://b.cn');
    }

    window.addEventListener('message',function(e){
        console.log('a:',e);        var color=e.data;
        document.getElementById('color').style.backgroundColor=color;
    },false);script>body>html>

b.cn/b.html

<!doctype html><html><head>
    <style type="text/css">
        html,body{
            height:100%;
            margin:0px;
        }
    style>head><body style="height:100%;"><div id="container" onclick="changeColor();" style="widht:100%; height:100%; background-color:rgb(204, 102, 0);">
    click to change colordiv><script type="text/javascript">
    var container=document.getElementById('container');

    window.addEventListener('message',function(e){        if(e.source!=window.parent) return;        var color=container.style.backgroundColor;
        window.parent.postMessage(color,'*');
    },false);    function changeColor () {        var color=container.style.backgroundColor;        if(color=='rgb(204, 102, 0)'){
            color='rgb(204, 204, 0)';
        }else{
            color='rgb(204,102,0)';
        }
        container.style.backgroundColor=color;
        window.parent.postMessage(color,'*');
    }script>body>html>

  

标签:postMessage,cn,script,color,跨源,通信,window
来源: https://blog.51cto.com/huangkui/2756478