几种跨域方式的演示

2017-09-15  本文已影响0人  zh_yang

一、JSONP

JSONP原理

无后端服务器演示JSONP

    127.0.0.1   aa.zhihaoy.com
    127.0.0.1   bb.zhihaoy.com

这样我们在127.0.0.1布置了两个域名

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>aaa</title>
</head>
<body>
<p id="aaa">aaa</p>
    <script type="text/javascript">
        function xxx (data) {
            var p = document.getElementById('aaa')
            p.innerText=('姓名:'+data.name+'\n'+'年龄:'+data.age)
        }
    </script>
    <script type="text/javascript" src="http://bb.zhihaoy.com/test.txt"></script>
</body>
</html>
xxx({name:'jrengu',age:3})
测试01.png
注释掉模拟执行请求的script标签,在浏览器地址栏输入http://aa.zhihaoy.com/a.html
页面显示: 测试02.png
还原模拟执行请求的script标签,刷新页面(请求的地址是:http://bb.zhihaoy.com/test.txt 测试03.png 测试04.png

这样就跨域获得并执行了数据,关键在于双方约定的xxx( )函数,否则拿到数据也不执行。

server mock 演示 JSONP

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>aaa</title>
</head>
<body>
<p id="aaa">aaa</p>
    <script type="text/javascript">
        function getWeather (data) {
            var p = document.getElementById('aaa')
            p.innerText=('杭州:'+data.weather)
        }
    </script>
    <script type="text/javascript" src="http://127.0.0.1:8080/getWea?city=hangzhou&callBack=getWeather"></script>
    //获取杭州天气
</body>
</html>
测试05.png 测试06.png 测试07.png 测试08.png

尝试封装JSOP

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>aaa</title>
</head>
<body>
    <p id="aaa">aaa</p>
    <script type="text/javascript">
        function getWeather(data){
            var p = document.getElementById('aaa')
            p.innerText=('杭州:'+data.weather)
        }
        function jsonP (url,callBack,data) {
            var script = document.createElement('script')
            script.src = url+'?'+data+'&callBack='+callBack
            document.head.appendChild(script)
            document.head.removeChild(script)
        }
        jsonP ("http://127.0.0.1:8080/getWea",'getWeather','city=hangzhou')
    </script>
</body>
</html>

测试后效果一样

二、CORS

原理:

在HTTP请求里添加特殊的头,允许服务器指定特定的域名可以跨域访问。

server mock 演示 CORS

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>aaa</title>
</head>
<body>
    <input id="inta" type="button" value="获取天气">
    <p>我是AAA</p>
    <script type="text/javascript" src="myAJAX.js"></script>
    <script type="text/javascript">
        var btna = document.getElementById('inta')
        var p = document.getElementsByTagName('p')[0]
        btna.onclick = function () {
            myAJAX('GET','http://127.0.0.1:8080/getWea?city=hangzhou',function(data){
                p.innerText = '杭州:' + JSON.parse(data).weather
            })
        }
    </script>
</body>
</html>
/**
 * 当 http://localhost:8080/getFriends 的GET请求到来时被下面匹配到进行处理
 * 通过req.query获取请求的参数对象 
 * 通过 req.send发送响应
 */
router.get('/getWea', function(req, res) { 
  var city = req.query.city // 通过 req.query获取请求参数
  var data
    //根据请求参数mock数据
  switch (city) {
    case 'hangzhou':
      data = {
        weather: "多云"
      }
      break
    case 'shanghai':
      data = {
        weather: "中雨"
      }
      break;
    default:
      data = {
        weather: "无信息"
      }
  }
  res.send(data)
})
router.get('/getWea', function(req, res) {
  res.header('Access-Control-Allow-Origin', 'http://aa.zhihaoy.com')
  //或者res.header('Access-Control-Allow-Origin', '*');
  //设置 header 
  var city = req.query.city // 通过 req.query获取请求参数
  var data
    //根据请求参数mock数据
  switch (city) {
    case 'hangzhou':
      data = {
        weather: "多云"
      }
      break
    case 'shanghai':
      data = {
        weather: "中雨"
      }
      break;
    default:
      data = {
        weather: "无信息"
      }
  }
  res.send(data)
})

刷新a.html得到:


测试10.png 测试11.png

三、降域document.domain

原理:

操作iframe,这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域同时为两个域设置document.domain= xxx.com

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>aaa</title>
</head>
<body>
    <input id="inta" type="text" placeholder="aaa">
    <p>我是AAA</p>
    <iframe src="http://bb.zhihaoy.com/b.html" width="300px" height="200px" style="border: 1px dotted"></iframe>
    <script type="text/javascript">
        //document.domain= 'zhihaoy.com'   默认不降域
        var btna = document.getElementById('inta')
        btna.oninput = function(){
            window.frames[0].document.getElementById('intb').value = this.value
        }
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>bbb</title>
</head>
<body>
    <input id="intb" type="text" placeholder="bbb">
    <p>我是BBB</p>
    <script type="text/javascript">
        //document.domain= 'zhihaoy.com'   默认不降域
        var btnb = document.getElementById('intb')
        btnb.oninput = function(){
            window.parent.document.getElementById('inta').value = this.value
        }
    </script>
</body>
</html>
测试13.png

postMessage

原理

postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

postMessage(data,origin)方法接受两个参数

1.data:要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js可以实现类似效果。

2.origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

演示postMessage

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>aaa</title>
</head>
<body>
    <input id="inta" type="text" placeholder="aaa">
    <p>我是AAA</p>
    <iframe src="http://bb.zhihaoy.com/b.html" width="300px" height="200px" style="border: 1px dotted"></iframe>
    <script type="text/javascript">
        var btna = document.getElementById('inta')
        btna.oninput = function(){
            window.frames[0].postMessage(this.value,'*')
        }
        window.addEventListener('message',function(e){
            btna.value.e.data
        })
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>bbb</title>
</head>
<body>
    <input id="intb" type="text" placeholder="bbb">
    <p>我是BBB</p>
    <script type="text/javascript">
        var btnb = document.getElementById('intb')
        btnb.oninput = function(){
            window.parent.postMessage(this.value,'*')
        }
        window.addEventListener('message',function(e){
            btnb.value=e.data
        })
    </script>
</body>
</html>
测试14.png
上一篇下一篇

猜你喜欢

热点阅读