js跨域请求

js跨域请求,原文地址

  1. 同源策略

    所有的浏览器都遵守同源策略,这个策略能够保证一个源的动态脚本不能读取或操作其他源的http响应和cookie,这就使浏览器隔离了来自不同源的内容,防止它们互相操作。所谓同源是指协议、域名和端口都一致的情况。举例来说,首先在Nginx上配置两个虚拟主机,一个监听80端口,另一个监听81端口:
    

    [plain] view plain copy print?
    server {

    listen 80;  
    server_name localhost;  
    
    location / {  
        root   D:/dev/workspace;  
                index  index.html index.htm;  
    }  
    
    location ~ \.php$ {  
        # 委托给后端的php  
        }  
    

    }

    81端口的server配置是类似的,只是端口不同而已,所以通过80和81端口会访问到相同的东西。写两个php,一个是用于页面展示的show_person.php,另一个是用于生成json数据的person.php。
    

    [php] view plain copy print?
    // show_person.php








[php] view plain copy print?
// person.php

<?php
$person = array(‘name’ => ‘kobe’, ‘age’ => 34);
echo json_encode($person);
?>
注意show_person.php中通过jQuery的getJSON请求http://localhost:80/MongoTest/person.php,这里是80端口。
然后先访问80端口试试,键入url:http://localhost/cross_domain/show_person.php。会弹出对话框,显示:kobe, your age is 34。
然后再访问81端口,http://localhost:81/cross_domain/show_person.php,结果出错:
XMLHttpRequest cannot loadhttp://localhost/MongoTest/person.php. Origin http://localhost:81 is not allowed by Access-Control-Allow-Origin.

这就是同源策略作用的效果。因为浏览器中访问的是81端口的内容,而show_person.php中请求的是80端口,所以请求的是不同源的内容,浏览器直接阻止这次请求。
  1. 打破同源策略的限制
    浏览器会阻止ajax请求非同源的内容,但没有限制<script>标签来访问非同源的内容,也没有限制使用动态添加<script>标签,所以可以采用这种方式打破这种限制。先测试下<script>访问非同源的内容,修改show_person.php,如下:
    
    [php] view plain copy print?
    // show_person.php




    <script type="text/javascript" src="http://localhost:80/MongoTest/person.php" ></script>  
</head>  
<body>  
</body>  


还需要对person.php略微修改,以实现函数调用:
[php] view plain copy print?
// person.php

<?php
$person = array(‘name’ => ‘kobe’, ‘age’ => 34);
echo ‘sayHello(‘.json_encode($person).’)’;
?>
实际上,通过之间。访问80和81端口,都会得到希望得到的结果:kobe, your age is 34。
下面就看一下,动态添加





person.php再做修改:
[php] view plain copy print?
// person.php

<?php
$person = array(‘name’ => ‘kobe’, ‘age’ => 34);
echo $_REQUEST[‘callback’].’(‘.json_encode($person).’)’;
?>
通过81端口访问,发现也会打印出结果。这就实现了跨域请求,可以通过firefox的firebug或者chrome的js控制台查看html元素发现,在head元素上多了一个

  1. JSONP
    实际上,上面的例子就是一个JSONP的简单实现。JSONP(JSON with Padding)就是服务器端和客户端互相协作以完成跨域请求的一种协议,客户端向服务器端发送请求并附带callback函数,服务器端返回相应的js代码,这个代码就是执行回调函数,参数就是服务器端返回的JSON数据。上面例子中的person.php就是服务端的简单实现,返回的响应内容是sayHello({"name":"kobe","age":34}),这段内容会被客户端插入到动态生成的script标签内部。
    客户端在发起跨域请求时,需要制定具体的回调函数,比如这个请求http://localhost:80/MongoTest/person.php?callback=sayHello,callback就是回调函数,服务器端也要通过callback要提取回调函数名,所以具体的这个参数需要客户端和服务器端达成一致,否则不能实现跨域。
    在jQuery中拥有对JSONP的支持,只要在使用jQuery.getJSON方法时传入的url的格式是url?callback=?即可,jQuery会自动的将?替换成具体的回调函数名。上面例子的功能,可以采用jQuery改写成:
    
    [javascript] view plain copy print?
    $.getJSON(‘http://localhost:80/MongoTest/person.php?callback=?‘, function(data){
    sayHello(data);
    });
    访问81端口,可以得到正确的响应。观察一下,发现person.php的响应内容是:
            jQuery17103600438670255244_1331202380099({"name":"kobe","age":34})
    前面的jQuery17103600438670255244_1331202380099就是jQuery动态生成的回调函数名,然后在这个回调函数内容调用后面定义的匿名函数,并将得到的JSON数据传进去。jQuery可以优化JSONP请求,如果向同一个源发出请求,jQuery 就将其转化为普通 Ajax 请求。
    
文章目录
,