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来进行跨域,就是这样子的。

     
  • 相关阅读:
    线程阶段性总结——APM,ThreadPool,Task,TaskScheduler ,CancellationTokenSource
    研究BackgroundWorker后发现:AsyncOperation和SynchronizationContext的差异真的很大!
    线程同步——优势、劣势
    APM异步编程模型的优势
    DataGridView的VirtualMode,在大容量数据加载时特别有用
    【C】——C语言的位运算的优势
    【linux】——Linux tar打包命令
    【C】用文件和链表实现学生信息管理
    【C】——回调函数的好处
    【C】strcpy()需谨慎使用;
  • 原文地址:https://www.cnblogs.com/jeffry/p/5486890.html
Copyright © 2011-2022 走看看