zoukankan      html  css  js  c++  java
  • js跨域访问

    问题:哪些类型的地址访问属于跨域访问

    URL类型 Intranet Url(缩写) 说明 是否允许访问
    http://www.xxyy.com/1.js
    http://www.xxyy.com/2.js
    http://ecapp01/1.js
    http://ecapp02/2.js
    同一域名下 YES
    http://www.xxyy.com/1.js
    http://www.xxyy.com/b/2.js
    http://ecapp01/1.js
    http://ecapp02/b/2.js
    同一域名下不同文件夹 YES
    http://www.xxyy.com/1.js
    https://www.xxyy.com:1234/2.js
    http://ecapp01/1.js
    http://ecapp02:9090/b/2.js
    同一域名下端口不通 NO
    http://www.xxyy.com/1.js
    http://www.cc.xxyy.com/2.js
    http://ecapp01/1.js
    http://ecapp03/2.js
    主域名相同,子域名不同,
    Intranet下两台IIS服务器位于不同域下
    NO
    http://www.xxyy.com/a.js
    http://www.xxyy.com/childsite/b.js
    http://ecapp01/1.js
    http://ecapp01/childsite/2.js
    同服务器子站点 YES

    实例场景:

    生产环境工作流平台发布在服务器:srvflow.ent.com.cn

    测试环境工作流平台发布在服务器:srvflowtest.test.dom

    生产环境业务表单发布在服务器:srvbizform.ent.com.cn

    测试环境业务表单发布在服务器:srvbizformtest.test.dom

    应用程序未B/S架构

    工作流平台希望通过IFrame集成各业务表单,实现加载各业务表单,和操作审批

    平台与各业务表单遵循参数与接口定义

    场景问题:

    测试环境下通过IFrame作业正常,当业务表单是测试环境应用,而工作流里作业平台是生产环境服务器,则产生了JS跨域访问问题

    解决方法:

    由于必须要使用Iframe,因此要保证主域一致;

    在srvflow.ent.com.cn创建业务表单分别创建测试站点和生产站点,由此保证主域相同

    但工作流作业平台应用站点与业务表单站点端口不通,因此仍然属于跨域访问,但这时问题已经变得简单了

    1. 工作流平台html设定

    document.domain = 'srvflow.ent.com.cn';

    2. 业务表单html设定

    document.domain = 'srvflow.ent.com.cn';

    如此可通过框架自由操作业务表单了

    iframework.submit('" + doitem.Parms + "');

    **************************************************附录**********************************************************

    一、通过jsonp跨域

    1. 通过引用文件方式

    在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

    比如,有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,

    假设这个json数据地址是http://example.com/data.aspx,那么a.html中的代码就可以这样:

    <script>

    funcion callback()

    {

    //do something

    }

    </script>

    <script src='http://example.com/data.aspx?callback=callback'></script>

    我们看到获取数据的地址后面还有一个callback参数,按惯例是用这个参数名,但是你用其他的也一样。当然如果获取数据的jsonp地址页面不是你自己能控制的,就得按照提供数据的那一方的规定格式来操作了。

    因为是当做一个js文件来引入的,所以http://example.com/data.aspx返回的必须是一个能执行的js文件,所以这个页面的后台代码可能是这样的:

     protected void Page_Load(object sender, EventArgs e)
            {
                string result = "callback({"name":"zhangsan","date":"2012-12-03"})";
    
                Response.Clear();
                Response.Write(result);
                Response.End();
            }
    客户端完整代码可能像这样
    <script type="text/javascript">
    
            var result = null;
            window.onload = function () {
                var script = document.createElement("script");
                script.type = "text/javascript";
                script.src = "http://example.com/data.aspx";
                var head = document.getElementsByTagName("head")[0];
                head.insertBefore(script, head.firstChild);
            };
            function callback(data) {
                result = data;
            }
    
            function b_click() {
                alert(result.name);
            }
        </script>
     2. 通过jquery
    <script type="text/javascript">
    $.getJSON('http://example.com/data.aspx',function(data){
    //do something
    })
    </script>
    原理是一样的,只不过我们不需要手动的插入script标签以及定义回掉函数。jquery会自动生成一个全局函数来替换callback=?中的问号,
    之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方 法;
    跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

    二、通过修改document.domain来跨子域

    
    

    浏览器都有一个同源策略,

    其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。

    它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。有一点需要说明,不同的框架之间(父子或同辈),是能够获取到彼此的window 对象的,但蛋疼的是你却不能使用获取到的window对象的属性和方法(html5中的postMessage方法是一个例外,还有些浏览器比如ie6也 可以使用top、parent等少数几个属性),总之,你可以当做是只能获取到一个几乎无用的window对象。比如,有一个页面,它的地址是http://www.example.com/a.html  , 在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:

    <script>
    function btn_click(){
    var ifm=document.getElementById('iframework')
    var cont=ifm.ContentWindow;
    alert(cont.document);//null
    alert(cont.name);//null
    }

    </script>
    
    

    这个时候,document.domain就可以派上用场了,我们只要把http://www.example.com/a.htmlhttp://example.com/b.html这 两个页面的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,因为主域已经不相同了。

    
    

    在页面 http://www.example.com/a.html 中设置document.domain:

    document.domain = 'srvflow.ent.com.cn';

    在页面 http://example.com/b.html 中也设置document.domain,而且这也是必须的,虽然这个文档的domain就是example.com,但是还是必须显示的设置document.domain的值:

    document.domain = 'srvflow.ent.com.cn';

    这样我们就可以通过js访问到iframe中的各种属性和对象了。

    不过如果你想在http://www.example.com/a.html 页面中通过ajax直接请求http://example.com/b.html 页面,即使你设置了相同的document.domain也还是不行的,所以修改document.domain的方法只适用于不同子域的框架间的交互。 如果你想通过ajax的方法去与不同子域的页面交互,除了使用jsonp的方法外,还可以用一个隐藏的iframe来做一个代理。原理就是让这个 iframe载入一个与你想要通过ajax获取数据的目标页面处在相同的域的页面,所以这个iframe中的页面是可以正常使用ajax去获取你要的数据 的,然后就是通过我们刚刚讲得修改document.domain的方法,让我们能通过js完全控制这个iframe,这样我们就可以让iframe去发 送ajax请求,然后收到的数据我们也可以获得了。

    三、使用window.name来进行跨域

    window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个 window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因 新页面的载入而进行重置。

    比如:有一个页面a.html,它里面有这样的代码:

    window.name='this is a.html data';

    页面b.html,它里面有这样的代码:

    alert(window.name);

    我们看到在b.html页面上成功获取到了它的上一个页面a.html给window.name设置的值。如果在之后所有载入的页面都没对 window.name进行修改的话,那么所有这些页面获取到的window.name的值都是a.html页面设置的那个值。当然,如果有需要,其中的 任何一个页面都可以对window.name的值进行修改。注意,window.name的值只能是字符串的形式,这个字符串的大小最大能允许2M左右甚 至更大的一个容量,具体取决于不同的浏览器,但一般是够用了。

    上面的例子中,我们用到的页面a.html和b.html是处于同一个域的,但是即使a.html与b.html处于不同的域中,上述结论同样是适用的,这也正是利用window.name进行跨域的原理。

    下面就来看一看具体是怎么样通过window.name来跨域获取数据的。还是举例说明。

    比如有一个www.example.com/a.html页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面www.cnblogs.com/data.html里的数据。

    data.html页面里的代码很简单,就是给当前的window.name设置一个a.html页面想要得到的数据值。data.html里的代码:

    那么在a.html页面中,我们怎么把data.html页面载入进来呢?显然我们不能直接在a.html页面中通过改变 window.location来载入data.html页面,因为我们想要即使a.html页面不跳转也能得到data.html里的数据。答案就是在 a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到 iframe获取到的数据。

    充当中间人的iframe想要获取到data.html的通过window.name设置的数据,只需要把这个iframe的src设为www.cnblogs.com/data.html就 行了。然后a.html想要得到iframe所获取到的数据,也就是想要得到iframe的window.name的值,还必须把这个iframe的 src设成跟a.html页面同一个域才行,不然根据前面讲的同源策略,a.html是不能访问到iframe里的window.name属性的。这就是 整个跨域过程。

    上面的代码只是最简单的原理演示代码,你可以对使用js封装上面的过程,比如动态的创建iframe,动态的注册各种事件等等,当然为了安全,获取完数据后,还可以销毁作为代理的iframe。网上也有很多类似的现成代码,有兴趣的可以去找一下。

    通过window.name来进行跨域,就是这样子的。

     
  • 相关阅读:
    jquery实现选项卡(两句即可实现)
    常用特效积累
    jquery学习笔记
    idong常用js总结
    织梦添加幻灯片的方法
    LeetCode "Copy List with Random Pointer"
    LeetCode "Remove Nth Node From End of List"
    LeetCode "Sqrt(x)"
    LeetCode "Construct Binary Tree from Inorder and Postorder Traversal"
    LeetCode "Construct Binary Tree from Preorder and Inorder Traversal"
  • 原文地址:https://www.cnblogs.com/jeffry/p/5486890.html
Copyright © 2011-2022 走看看