一、通过jsonp跨域

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

http://localhost:23383/Home/Index这个页面想跨域请求http://www.jscrossdomain.com/home/index的数据,www.jscrossdomain.com是服务器(也就是本地要模拟从服务器请求数据):

服务器端代码:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var fun = Request["callback"] != null ? Request["callback"].ToString() : "a";
            string result = fun + "({\"name\":\"zhangsan\",\"date\":\"2015-4-30\"})";

            return Content(result);
        }
    }

客户端(跨域请求端):

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
    <script src="../../Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
    <script type="text/javascript">

        var result = null;
        window.onload = function () {
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.src = "http://www.jscrossdomain.com/home/index?callback=callback";

            var head = document.getElementsByTagName("head")[0];
            head.insertBefore(script, head.firstChild);

        };

        function callback(data) {
            alert("我是被自动调用的");
            result = data;
        }

        function b_click() {
            alert(result.name + "|" + result.date);
        }
    </script>
</head>
<body>
    <div>
         <input type="button" value="click me!" onclick="b_click();" />
    </div>
</body>
</html>

客户端页面加载完毕,弹框,点击button弹框显示跨域请求数据。

二、通过ajax跨域请求

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
    <script src="../../Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        function b_click() {
            $.ajax({
                async: false,
                url: "http://www.jscrossdomain.com/home/index",
                type: "GET",
                dataType: 'jsonp',
                //jsonp的值自定义,如果使用jsoncallback,那么服务器端,要返回一个jsoncallback的值对应的对象.
                jsonp: 'callback',
                //要传递的参数,没有传参时,也一定要写上
                data: null,
                timeout: 5000,
                //返回Json类型
                contentType: "application/json;utf-8",
                //服务器段返回的对象包含name,data属性.
                success: function (result) {
                    alert(result.name + "|" + result.date);
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    alert(textStatus);
                }
            });
        }
    </script>
</head>
<body>
    <div>
         <input type="button" value="click me!" onclick="b_click();" />
    </div>
</body>
</html>

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

posted on 2015-04-30 17:16  零点漂移  阅读(266)  评论(0编辑  收藏  举报