跨域的实现方式

什么是跨域

只要协议、域名、端口有任何一个不同,都被当作是不同的域,对于端口和协议的不同只能通过后端来解决。浏览器一般情况下一个页面不能访问另外一个页面的脚本信息。

跨域的实现方法

跨域的实现方法有如下几种

JSONP

JSONP是JSON padding的简写,是应用JSON的一种新方法,在web服务中非常流行,JSONP看起来和JSON差不多,只不过是被包含在函数中的JSON。类似下面这样

callback({"name": "Nicolas" })

JSON由两部分组成:回调函数和数据,回调函数是当页面响应的时候页面调用的数据。回调函数的名字一般在请求中指定的。而数据就是传入回调函数的JSON数据。比如
http://jrg.com/index.html?callback=handler
这里指定的回调函数名字就是handler()。
JSONP是通过动态<script>标签来使用的,使用时候可以为src属性指定一个跨域URL。<script>元素和<img>元素类似,都有能力不受限制从其他域中加载资料。又因为JSONP是有效的javascript代码,因此在加载完成之后,就会立即执行。比如下面例子

function handleResponse(response){
    console.log("You`re at IP address" + response.ip + ", which is in" 
                + response.city + ", " + response.region_name);
}

var script = document.createElement("script");
srcipt.src = "htt[://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);

这个例子通过查询地理位置定位服务来显示Ip和位置信息。
JSONP在开发人员中非常流行,主要原因是JSONP简单易用,与图像ping相比,它的优点在于可以直接访问相应文本,支持在浏览器与服务器之间的双向通信,但是它也有不足的地方。
不足的地方体现在两个方面,首先JSONP从其他域中加载代码执行,如果其他域不安全,很有可能在响应中夹带着恶意代码,而此时出了完全放弃JSONP调用之外,没有办法追究。其次要确定JSONP请求是否失败并不容易。虽然HTML5给<script>元素新增了一个onerror事件处理程序,但是目前没有得到任何浏览器的支持。为此,开发人员不得不使用计时器检测指定时间是否收到响应。
具体例子如下

//前端
<html>
<head>
<style>
.container{
  width: 900px;
  margin: 0 auto;
}
</style>
</head>
<body>
<div class = "container">
  <ul class = "news">
    <li>第11日前瞻:中国冲击4金 博尔特再战</li>
    <li>双力争会师决赛</li>
    <li>女排将死磕巴西</li>
  </ul>
  <button class ="switch">换一组</button>
</div>
</boyd>
<script>
 var btn = document.querySelector(".switch");
 var container = document.querySelector(".news")
 btn.addEventListener("click", function(){
    var script = document.createElement("script");
    script.src = 'http://localhost:8080/getNews?callback=appendHtml';
    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);
        container.innerHTML = html;
    }
 }

</script>
</html>
//后端
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);
    }

    var cb = req.query.callback
    if(cb){
        res.send(cb + '('+ JSON.stringify(data) + ')');
    }else{
        res.send(data);
    }
})

CORS(cross-origin-resource-sharing)

CORS是cross-origin-resrouce-sharing的缩写,定义了在必须访问跨域资源时,浏览器与服务器之间如何沟通,CORS后面的思想是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求是成功还是失败。
比如一个简单的使用GET和POST发送的请求,它没有自定义头部,主体内容是text/plain。在发送请求的时候,必须给它附加一个额外的origin头部,其中包含请求页面的信息,以便服务器根据这个头部来决定是否给予响应。下面是origin头部的一个示例。

origin: http://www.jirengu.com

如果服务器认为这个请求可以接收,就在access-control-allow-origin头部中回发相同的源信息(如果是公共资源,可以回发"*")。例如

Access-Control-Allow-Origin:http://www.jirengu.com

如果没有这个头部,或者有这个头部但是源信息不匹配,浏览器就会驳回请求。正常情况下,浏览器会处理这个请求。请求和响应都不包含cookie信息。
具体例子如下

//前端
<html>
<head>
<style>
.container{
  width: 900px;
  margin: 0 auto;
}
</style>
</head>
<body>
<div class = "container">
  <ul class = "news">
    <li>第11日前瞻:中国冲击4金 博尔特再战</li>
    <li>双力争会师决赛</li>
    <li>女排将死磕巴西</li>
  </ul>
  <button class ="switch">换一组</button>
</div>
</boyd>
<script>
 var btn = document.querySelector(".switch");
 var container = document.querySelector(".news")
 btn.addEventListener('click', function(){
    var xhr = new XMLHttpRequest();
    xhr.open('get', 'http://localhost:8080/getNews', true);
    xhr.send();
    xhr.onreadystatechange = function(){
      if(xhr.readyState === 4 && xhr.status === 200){
        var result = JSON.parse(xhr.responseText);
        var html ='';
        for(var i = 0; i < result.length; i++){
          html += '<li>' + result[i] + '</li>';
          container.innerHTML = html;
        }
      }
    }
 })
</script>
</html>
//后端
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(news[index], 1);
    }
    res.header("Access-Control-Allow-Origin", "*");
    res.send(data);
});

降域

//a部分
<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://localhost:8080/a.html">
  </div>

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

</div>


<script>
  var ipt = document.querySelector('.main input');
  ipt.addEventListener('input', function(){
  window.frames[0].document.querySelector('input').value = this.value;
})
document.domain = "hello.com"
</script>
</html>
//b部分
<html>
<style>
    html,body{
        margin: 0;
    }
    input{
        margin: 20px;
        width: 200px;
    }
</style>

    <input id="input" type="text"  placeholder="http://localhost:8080/b.html">
<script>
// URL: http://b.jrg.com:8080/b.html
var ipt = document.querySelector('#input');
ipt.addEventListener('input', function(){
    window.parent.document.querySelector('input').value = this.value;
})
document.domain = 'hello.com';
</script>
</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 前言:对于跨域请求,很早之前就有去了解过,但因为一直关注的都是服务器后端开发,故也就仅仅停留在概念的理解上而没有机...
    ken_ljq阅读 89,708评论 6 128
  • 1. AJAX AJAX(Asynchronous JavaScript and XML),意思就是用JavaSc...
    公子七阅读 4,987评论 0 5
  • 什么是同源策略 同源策略(Same origin Policy):浏览器出于安全方面的考虑,只允许与本域下的接口交...
    _Dot912阅读 834评论 0 3
  • 什么是同源策略 同源政策(same-origin policy)是指同域名(或ip),同端口,同协议视为同一个域,...
    小囧兔阅读 491评论 0 1
  • 一、浏览器的同源策略 1.什么是同源? 所谓“同源”指的是”三个相同“。相同的域名、端口和协议,这三个相同的话就视...
    徐国军_plus阅读 833评论 1 3