js__JSONP__跨域

2017-05-11  本文已影响56人  好奇而已

1: 什么是同源策略

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

不跨域会出现图片的的报错

跨域常见方式

//在页面 http://www.example.com/a.html 中设置document.domain:
<iframe src="example.com/b.html" id="iframe" onload="test()"></iframe>
    <script>
        document.domain='example.com';//设置成主域
        function test(){
            alert(document.getElementById('iframe').contentWindow);
        }
    </script>
//在页面 http://example.com/b.html中也设置document.domain
<script>
        document.domain='example.com';//在iframe载入的这个页面也设置 document.domain与主页面相同
</script>
//而且是必须的,虽然这个文档的domain就是example.com,但是还是必须显示的设置document.domain的值

3: JSONP 的原理是什么

4: CORS是什么

浏览器将CORS请求分成两类:简单请求(simple request)和
简单请求条件
1) 请求方法是以下三种方法中的一个:
HEAD
GET
POST
2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同时满足上面两个条件,就属于非简单请求

app.get('/getNews', function(req, res){

    var news = [
        "第11日前瞻:中国冲击4金 博尔特再战200米羽球",
    ]
    var data = [];
    for(var i=0; i<3; i++){
        var index = parseInt(Math.random()*news.length);
        data.push(news[index]);
        news.splice(index, 1);
    }
    res.header("Access-Control-Allow-Origin", "http://a.jrg.com:8080"); //代表只接受http://a.jrg.com:8080网址的请求
    //res.header("Access-Control-Allow-Origin", "*"); //*表示接受任意域名的请求

    res.send(data);
})

跨域问题
跨域10种方式

5: 演示三种常用以上跨域的解决方式

router.js


app.get('/getNews', function(req, res){
var news = [
'我没有特别的才能,只有强烈的好奇心。永远保持好奇心的人是永远进步的人。——爱因斯坦',

'爱因斯坦认为他之所以取得成功,原因在于他具有狂热的好奇心.',
'求知欲,好奇心这是人的永恒的,不可改变的特性。哪里没有求知欲,哪里便没有学校。——苏霍姆林斯基',

'孩子提出的问题越多,那么他在童年早期认识周围的东西也就愈多,在学校中越聪明,眼睛愈明,记忆力愈敏锐。要培养自己孩子的智力,那你就得教给他思考。——苏霍姆林斯基',

'我想起了自己小学的学习经历,终于理解了为什么小时候成绩好,我那时候确实好奇心非常强烈.',
'人的内心里有一种根深蒂固的需要——总想感到自己是发现者、研究者、探寻者。在儿童的精神世界中,这种需求特别强烈。但如果不向这种需求提供养料,即不积极接触事实和现象,缺乏认识的乐趣,这种需求就会逐渐消失,求知兴趣也与之一道熄灭。(苏霍姆林斯基)',

'生活的全部意义在于无穷地探索尚未知道的东西,在于不断地增加更多的知识。——左拉'
    ]
    var data = [];
    for(var i=0; i<3; i++){
        var index = parseInt(Math.random()*news.length);
        data.push(news[index]);
        news.splice(index, 1);//把data数组里已经有的元素从news数组里删除,保证不重复上一步拿到的新闻
    }
    var cb = req.query.callback
    if(cb){
        res.send(cb + '('+ JSON.stringify(data) + ')');
    }else{
        res.send(data);
    }   
})

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>news</title>
<style>
  .container{
    width: 900px;
    margin: 0 auto;
  }
</style>
</head>
<body>
  <div class="container">
    <ul class="news">
      <li>我没有特别的才能,只有强烈的好奇心 ——爱因斯坦</li>
      <li>我没有特别的才能,只有强烈的好奇心 ——爱因斯坦</li> 
      <li>我没有特别的才能,只有强烈的好奇心 ——爱因斯坦</li>
    </ul>
    <button class="change">点我换一组</button>
  </div>
  
<script>
  
  $('.change').addEventListener('click', function(){
    var script = document.createElement('script');
    script.src = 'http://gaygay.com:8080/getNews?callback=appendHtml';//必须是'http://xxx.com:8080/的形式
   
    document.head.appendChild(script);
    document.head.removeChild(script);
  })
  
  function appendHtml(news){
    var html = '';
    for( var i=0; i<news.length; i++){
      html += '<li>' + news[i] + '</li>';
    }
    console.log(html);
    $('.news').innerHTML = html;
  }
  function $(id){//$函数,发请求前和点击换一组都调用.传入参数,直接返回.
    return document.querySelector(id);//替换$(id)为document.querySelector(id),因为浏览器不支持jquery库
  }
</script>

</body>

</html>

结合上面的案例说下jsonp的本质:


后台判断:
 var cb = req.query.callback
    if(cb){
        res.send(cb + '('+ JSON.stringify(data) + ')');
    }

场景:
A网访问跨域的B网资源:
在A网通过给script标签的src赋值一个网址.
例子: var script = document.createElement('script');
    script.src = 'http://gaygay.com:8080/getNews?callback=appendHtml'

这个网址带有回调的方法名.加载script脚本到B网页,B网页发回消息去调用在A网页脚本里定义的回调函数.callback.

6.CORS案例

QQ20170512-220224-HD.gif
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>news</title>
<style>
 .container{
   width: 900px;
   margin: 0 auto;
 }
</style>
</head>
<body>
 <div class="container">
   <ul class="news">
     <li>CORS练习</li>
     <li>男双力争会师决赛 </li> 
     <li>女排将死磕巴西!</li>
   </ul>
   <button class="change">换一组</button>
 </div>
 
<script>
 
 $('.change').addEventListener('click', function(){
   var xhr = new XMLHttpRequest();
   xhr.open('get', 'http://b.jrg.com:8080/getNews', true);
   xhr.send();
   xhr.onreadystatechange = function(){
     if(xhr.readyState === 4 && xhr.status === 200){
       appendHtml( JSON.parse(xhr.responseText) )
     }
   }
   window.xhr = xhr//why?
 })
 function appendHtml(news){
   var html = '';
   for( var i=0; i<news.length; i++){
     html += '<li>' + news[i] + '</li>';
   }
   console.log(html);
   $('.news').innerHTML = html;
 }
 function $(id){
   return document.querySelector(id);
 }
</script>
</html>

router.js


app.get('/getNews', function(req, res){

    var news = [
        "第11日前瞻:中国冲击4金 博尔特再战200米羽球",
        "正直播柴飚/洪炜出战 男双力争会师决赛",
        "女排将死磕巴西!郎平安排男陪练模仿对方核心",
        "没有中国选手和巨星的110米栏 我们还看吗?",
        "中英上演奥运金牌大战",
        "博彩赔率挺中国夺回第二纽约时报:中国因对手服禁药而丢失的奖牌最多",
        "最“出柜”奥运?同性之爱闪耀里约",
        "下跪拜谢与洪荒之力一样 都是真情流露"
    ]
    var data = [];
    for(var i=0; i<3; i++){
        var index = parseInt(Math.random()*news.length);
        data.push(news[index]);
        news.splice(index, 1);
    }
    res.header("Access-Control-Allow-Origin", "http://jrg.com:8080"); 
    //res.header("Access-Control-Allow-Origin", "*"); 
    res.send(data);

7.document.domain降域

QQ20170513-104421-HD.gif

情景:a.html里面嵌入iframe元素,且这个iframe是<iframe src="http://b.jrg.com:8080/b.html" frameborder="0" ></iframe>,而b.html就是个其中src规定显示在 iframe 中的文档的地址,也是绝对 URL - 指向其他站点(比如 src="www.example.com/index.html"),这里是个非同源的b.html

//a.html文件

<html>
<style>
  .ct{
    width: 910px;
    margin: auto;
  }
  .main{
    float: left;
    width: 450px;
    height: 300px;
    border: 1px solid #ccc;
  }
  .main input{
    margin: 20px;
    width: 200px;
  }
  .iframe{
    float: right;
  }
  iframe{
    width: 450px;
    height: 300px;
    border: 1px dashed #ccc;
  }
</style>

<div class="ct">
  <h1>使用降域实现跨域</h1>
  <div class="main">
    <input type="text" placeholder="http://a.jrg.com:8080/a.html">
  </div>

  <iframe src="http://b.jrg.com:8080/b.html" frameborder="0" ></iframe>

</div>


<script>
//URL: http://a.jrg.com:8080/a.html
document.querySelector('.main input').addEventListener('input', function(){
  console.log(this.value);
  window.frames[0].document.querySelector('input').value = this.value;
})

document.domain = "jrg.com"//降域关键代码
</script>
</html>


//b.html
<html>
<style>
    html,body{
        margin: 0;
    }
    input{
        margin: 20px;
        width: 200px;
    }
</style>

    <input id="input" type="text"  placeholder="http://b.jrg.com:8080/b.html">
<script>

 
document.querySelector('#input').addEventListener('input', function(){
    window.parent.document.querySelector('input').value = this.value;
})
document.domain = 'jrg.com';
</script>
</html>


//a.html文件

<html>
<style>
    .ct{
        width: 910px;
        margin: auto;
    }
    .main{
        float: left;
        width: 450px;
        height: 300px;
        border: 1px solid #ccc;
    }
    .main input{
        margin: 20px;
        width: 200px;
    }
    .iframe{
        float: right;
    }
    iframe{
        width: 450px;
        height: 300px;
        border: 1px dashed #ccc;
    }
</style>

<div class="ct">
    <h1>使用postMessage实现跨域</h1>
    <div class="main">
        <input type="text" placeholder="http://a.jrg.com:8080/a.html">
    </div>

    <iframe src="http://localhost:8080/b.html" frameborder="0" ></iframe>

</div>


<script>
//URL: http://a.jrg.com:8080/a.html
$('.main input').addEventListener('input', function(){
    console.log(this.value);
    window.frames[0].postMessage(this.value,'*');//window.frames[0]是window子窗口的第一个.*代表任意地址

})
window.addEventListener('message',function(e) {
        $('.main input').value = e.data
    console.log(e.data);
});

//
window.addEventListener('message',function(e){
  $('.mian input').value = e.data;
})


function $(id){
    return document.querySelector(id);
}
</script>
</html>
//b.html文件:即被内嵌的iframe链接文档url.
<html>
<style>
    html,body{
        margin: 0;
    }
    input{
        margin: 20px;
        width: 200px;
    }
</style>

    <input id="input" type="text"  placeholder="http://b.jrg.com:8080/b.html">
<script>

 
 //传出数据到内嵌此窗口的父窗口即a.html.
$('#input').addEventListener('input', function(){
    window.parent.postMessage(this.value, '*');//
    //返回当前窗口的父窗口对象.如果一个窗口没有父窗口,则它的 parent 属性为自身的引用.
    //如果当前窗口是一个 <iframe>, <object>, 或者 <frame>,则它的父窗口是嵌入它的那个窗口
})

//接收信息
window.addEventListener('message',function(e) {
        $('#input').value = e.data
    console.log(e.data);
});
function $(id){
    return document.querySelector(id);
}   
</script>
</html>

跨域实例的代码参考

上一篇 下一篇

猜你喜欢

热点阅读