美文网首页
JS跨域问题

JS跨域问题

作者: trump2018 | 来源:发表于2019-03-19 21:37 被阅读0次

JS跨域问题

  • 协议不同
    如http, https;
  • 端口不同
  • 主域相同,子域不同
  • 主域不同
  • ip地址和域名
    浏览器不会自动做ip域名的映射

造成跨域的两种策略

浏览器的同源策略会导致跨域,这里同源策略又分为以下两种

DOM同源策略

禁止对不同源页面DOM进行操作。这里主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的。

XmlHttpRequest同源策略

禁止使用XHR对象向不同源的服务器地址发起HTTP请求。只要协议、域名、端口有任何一个不同,都被当作是不同的域,之间的请求就是跨域操作。

为什么要有跨域限制

了解完跨域之后,想必大家都会有这么一个思考,为什么要有跨域的限制,浏览器这么做是出于何种原因呢。其实仔细想一想就会明白,跨域限制主要是为了安全考虑。
AJAX同源策略主要用来防止CSRF攻击。如果没有AJAX同源策略,相当危险,我们发起的每一次HTTP请求都会带上请求地址对应的cookie,那么可以做如下攻击:用户登录了自己的银行页面 http://mybank.comhttp://mybank.com向用户的cookie中添加用户标识。用户浏览了恶意页面 http://evil.com。执行了页面中的恶意AJAX请求代码。http://evil.comhttp://mybank.com发起AJAX HTTP请求,请求会默认把http://mybank.com对应cookie也同时发送过去。银行页面从发送的cookie中提取用户标识,验证用户无误,response中返回请求数据。此时数据就泄露了。而且由于Ajax在后台执行,用户无法感知这一过程。
DOM同源策略也一样,如果iframe之间可以跨域访问,可以这样攻击:做一个假网站,里面用iframe嵌套一个银行网站 http://mybank.com。把iframe宽高啥的调整到页面全部,这样用户进来除了域名,别的部分和银行的网站没有任何差别。这时如果用户输入账号密码,我们的主网站可以跨域访问到http://mybank.com的dom节点,就可以拿到用户的输入了,那么就完成了一次攻击。

跨域的解决方式

解决方案

document.domain
window.name
jsonp
postMessage
cors

document.domain

  • 关键点
    跨域分为两种,一种xhr不能访问不同源的文档,另一种是不同window之间不能进行交互操作;
    document.domain主要是解决第二种情况,且只能适用于主域相同子域不同的情况;
    document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com中某个文档的document.domain可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。
  • 兼容性:所有浏览器都支持;
  • 优点
    可以实现不同window之间的相互访问和操作;
  • 缺点
    只适用于父子window之间的通信,不能用于xhr;
    只能在主域相同且子域不同的情况下使用;
  • 使用方式
    a(当前页面或父页面)页面中加入document.domain = ‘example.com’;
    b(当前页面或子页面)页面中加入document.domain = ‘example.com’;
    a页面访问b页面里面的数据或者方法;
  • Example
    有一个页面,它的地址是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是http://example.com/b.html
    1.在页面 http://www.example.com/a.html 中设置document.domain:
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
<script type="text/javascript">
    document.domain = 'example.com';//设置成主域
    function test(){
        alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象
    }
</script>

2.在页面 http://example.com/b.html 中也设置document.domain:

<script type="text/javascript">
    document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同
</script>

window.name

  • 关键点

  • window.name在页面的生命周期里共享一个window.name;

  • 兼容性

  • 所有浏览器都支持;

  • 优点
    最简单的利用了浏览器的特性来做到不同域之间的数据传递;
    不需要前端和后端的特殊配制;

  • 缺点
    大小限制:window.name最大size是2M左右,不同浏览器中会有不同约定;
    安全性:当前页面所有window都可以修改,很不安全;
    数据类型:传递数据只能限于字符串,如果是对象或者其他会自动被转化为字符串,如下;
    window.name非字符串测试
    使用方式:修改window.name的值即可;

  • Example
    a.html中代码:

<script>
    window.name = '我是页面a中设置的值';
    setInterval(function(){
        window.location = 'b.html';
    },2000)//两秒后把一个新页面b.html载入到当前的window中
</script>

b.html中的代码

<script>
    console.log(window.name);//读取window.name的值
</script>

jsonp

  • 关键点
    浏览器对XHR做了同源策略,但并没有将这种方式延续到script上(其实还有iframe,img等)
    从而可以利用动态script标签技术来做到跨域请求的作用。至于为什么会这样设计,本人也不太清楚,有可能是历史遗迹(漏洞),有可能是某些方面的技术瓶颈,也有可能是为了满足某些需求专门定制的,总之这项技术方案我们过去可以用,现在可以用就ok,至于将来应该也是会存在的,毕竟现在已经应用在很多家站点上,就算会废弃,也会有一段时间迭代。
    在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

  • 兼容性
    所有浏览器都兼容这种方式;

  • 优点
    很明显前端可以很轻松的做到跨域请求;

  • 缺点
    只能通过GET方式请求,一方面是参数长度有限制,二是安全性比较差;
    后端需要知道前端的cb是什么样的结构,主要在参数和回调名;
    后端需要进行参数和cb的拼接然后才能执行;

<script type="text/javascript">
    function dosomething(jsondata){
        //处理获得的json数据
    }
</script>
<script src="http://example.com/data.php?callback=dosomething"></script>

js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

<?php
$callback = $_GET['callback'];//得到回调函数名
$data = array('a','b','c');//要返回的数据
echo $callback.'('.json_encode($data).')';//输出
?>

最终,输出结果为:dosomething(['a','b','c']);

postMessage

  • 关键点
    window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

  • 兼容性
    移动端可以放心用,但是pc端需要做降级处理,具体可以根据文中介绍的这几种跨域方式来则情选择;

  • 优点
    不需要后端介入就可以非常简单的的做到跨域,一个函数外加两个参数(请求url,发送数据)就可以搞定;
    移动端兼容性好;

  • 缺点
    无法做到一对一的传递方式:监听中需要做很多消息的识别,由于postMessage发出的消息对于同一个页面的不同功能相当于一个广播的过程,该页面的所有onmessage都会收到,所以需要做消息的判断;
    安全性问题:三方可以通过截获,注入html或者脚本的形式监听到消息,从而能够做到篡改的效果,所以在postMessage和onmessage中一定要做好这方面的限制;
    发送的数据会通过结构化克隆算法进行序列化,所以只有满足该算法要求的参数才能够被解析,否则会报错,如function就不能当作参数进行传递;

  • 例子
    otherWindow.postMessage(message, targetOrigin);
    otherWindow: 对接收信息页面的window的引用。可以是页面中iframe的contentWindow属性;window.open的返回值;通过name或下标从window.frames取到的值。
    message: 所要发送的数据,string类型。
    targetOrigin: 用于限制otherWindow,“*”表示不作限制

  • Example
    a.com/index.html中的代码:

<iframe id="ifr" src="b.com/index.html"></iframe>
<script type="text/javascript">
window.onload = function() {
    var ifr = document.getElementById('ifr');
    // 若写成'http://b.com/c/proxy.html'效果一样
    // 若写成'http://c.com'就不会执行postMessage了
    var targetOrigin = 'http://b.com';  
    ifr.contentWindow.postMessage('I was there!', targetOrigin);
};
</script>

b.com/index.html中的代码:

<script type="text/javascript">
    window.addEventListener('message', function(event){
        // 通过origin属性判断消息来源地址
        if (event.origin == 'http://a.com') {
            alert(event.data);    // 弹出"I was there!"
            alert(event.source);  // 对a.com、index.html中window对象的引用
                                  // 但由于同源策略,这里event.source不可以访问window对象
        }
    }, false);
</script>

cors(Cross-origin resource sharing)

  • 关键点
  • cors是一种通过前后端http header配置来进行跨域的一种方式;
    兼容性:如果不考虑pc端的IE,移动端的opera的话那兼容性还是不错的,针对ie和opera可以做适当的降级处理;
    poseMessage兼容性
    安全策略
    请求
    origin:通过http头中的origin判断域名是否是允许的;
    Example-Same-origin:如果http origin不存在,最好能够自己在请求头中加入该参数来标示是否是同源,true表示请求来自于同域名下(同域名下请求不带origin);如果该字段存在并且为true则允许请求接口,否则禁止;
    Example_source_origin:该参数同origin,是在origin不存在的情况下用来标示请求来源的url;
    返回
    Access-Control-Allow-Origin: origin,origin表示允许哪些网站请求,不建议设置为*;
    Access-Control-Expose-Headers:Example-Access-Control-Allow-Source-Origin,允许http返回中包含该字段,可以通过这种方式在返回头中加入自定义字段,如该例子中的Example-Access-Control-Allow-Source-Origin;
  • 优点
    前端方便不少,只需要发请求而不用考虑跨域问题;
    安全性能够得以控制和保障;
  • 缺点
    兼容性不全面,需要做降级处理;
  • Example
    对于客户端,我们还是正常使用xhr对象发送ajax请求。唯一需要注意的是,我们需要设置我们的xhr属性withCredentials为true,不然的话,cookie是带不过去的哦,设置: xhr.withCredentials = true;对于服务器端,需要在 response header中设置如下两个字段:
    Access-Control-Allow-Origin: http://www.yourhost.com
    Access-Control-Allow-Credentials:true
    这样,我们就可以跨域请求接口了。

相关文章

  • 跨域

    跨域 什么是跨域: 解决跨域 通过jsonp原理:在页面引入跨域js和css时,没有存在跨域问题.因此可以动态创建...

  • HTML-获取iframe元素的正确方法

    跨域相关文章详解js跨域问题JavaScript跨域总结与解决办法 解释最清楚的jsonpWhat is JSON...

  • 怎么能学好Web前端开发,如何去解决JS跨域问题

    如何去解决JS跨域问题?怎么能学好Web前端开发?JavaScript跨域是指通过JS在不同的域之间进行数据传输或...

  • 如何去解决JS跨域问题 怎么能学好Web前端开发

    如何去解决JS跨域问题?怎么能学好Web前端开发?JavaScript跨域是指通过JS在不同的域之间进行数据传输或...

  • Ajax跨域问题解决方案

    想要解决跨域问题,首先要知道为什么会出现跨域问题? 由于JS同源策略的影响,因此js只能访问同域名下的文档。...

  • js跨域问题

    今天新网站(www.example.com)上线,主页面需要用ajax访问sms.example.com的短信发送...

  • js跨域问题

    前言 前端跨域通信,是实际项目开发中一个比较常见的问题,其中关于ajax跨域请求的场景尤为典型。 参考资料 浏览器...

  • JS跨域问题

    同源策略: 为了安全性,同源策略规定跨域之间的脚本是隔离的。一个域的脚本不能访问和操作另一个域的绝大部分属性和方法...

  • JS 跨域问题

    什么是跨域 跨域指的是浏览器不能执行别的网站的脚本。它是由浏览器的同源策略造成的。是浏览器对javascript施...

  • js跨域问题

    1.什么是跨域? 所谓跨域就是浏览器从一个域名的网页去请求另一个不同域名的资源 2.为什么存在跨域问题? 因为浏览...

网友评论

      本文标题:JS跨域问题

      本文链接:https://www.haomeiwen.com/subject/sclbmqtx.html