跨域及跨域访问

什么是跨域

跨域是一个域名的网页去请求另一个域名网页的资源。

这里有一点儿需要注意:跨域并非浏览器限制了发起跨站请求的这种能力,恰恰相反,我们可以发出请求,服务端也可以接收到请求并正常返回数据,只不过在返回之后浏览器会阻止非同源数据(response),从而在控制台打出一系列报错信息。所以我们调试的时候可以看到发出的请求和接收到的返回数据但是控制台报错。

哪些情况算跨域

下面这些情况都算跨域:

  • 主域不同(www.baidu.com访问www.google.com
  • 主域相同,子域不同(a.baidu.com访问b.baidu.com
  • 端口不同(www.baidu.com:8000访问www.baidu.com:80
  • 协议不同(http://www.baidu.com访问https://www.baidu.com
  • IP地址和域名(http://180.97.33.107访问http://www.baidu.com

有哪些解决方案

  • document.domain
  • window.name
  • jsonp
  • postMessage
  • CORS

document.domain

跨域分为两种,一种xhr不能访问不同源的文档,另一种是不同window之间不能进行交互操作。 这种方法主要是解决第二种情况并且是主域名相同子域名不同的情况。 而且document.domain的设置也是有限制的,只能设置成当前层次的域名或者更高层级的域名:如当前页面的域名是a.baidu.com的话,那么document.domain只能设置成a.baidu.com或者baidu.com,而不能设置成a.b.baidu.com

window.name

在页面的生命周期里面共享一个window.name,所以可以直接修改window.name的值来传递数据。

传输的大小有限制,一般为2M,IE和firefox下可以大至32M左右。

jsonp

浏览器对XHR做了同源策略,但并没有将这种方式延续到script上(其实还有iframe,img等),从而可以利用动态script标签技术来做到跨域请求的作用。

  1. 只能通过GET方式请求,一方面是参数长度有限制,二是安全性比较差;
  2. 后端需要知道前端的callback是什么样的结构,主要在参数和回调名;
  3. 后端需要进行参数和callback的拼接然后才能执行;
script:
$.ajax({
                type:'GET',
                dataType:'jsonp',
                url:'http://y500.me/xxx/index.php',
                data: {
                    a: 'getAlbums'
                },
                success:function(data,textStatus,jqXHR){
                    if(data.data){
                        //do what you want to do
                        }
                    } else {
                        alert('设置失败');
                    }
                },
                error:function(xhr,textStatus){
                    alert(textStatus);
                }
            });
php:
function result_json($info = '', $code = 10000, $data = array(), $location = '') {  
    $out['code'] = $code ?: 0;
    $out['info'] = $info ?: ($out['code'] ? 'error' : 'success');
    $out['data'] = $data ?: array();
    $out['location'] = $location;
    header('Content-Type: application/json');
    // echo json_encode($out, JSON_HEX_TAG);
    $jsondata = json_encode($out, JSON_HEX_TAG);
    echo $_GET['callback'].'('.$jsondata.')';
    exit(0);
}

postMessage

postMessage是h5引入的一个新概念,现在也在进一步的推广和发展中,他进行了一系列的封装,我们可以通过window.postMessage的方式进行使用,并可以监听其发送的消息。由于是h5引入的,所以呢移动端可以尽情的使用,但是PC端就要谨慎了。

CORS

全称:Cross-Origin Resource Sharing CORS是一种通过前后端http header配置来进行跨域的一种方式。除了PC端的IE和移动端的Opera,其他兼容性良好。

这种情况需要后端处理,前端就很方便,不用考虑跨域问题。后端要留意安全问题。

request
  • origin:通过http头中的origin判断域名是否是允许的;
  • Example-Same-origin:如果http origin不存在,最好能够自己在请求头中加入该参数来标示是否是同源,true表示请求来自于同域名下(同域名下请求不带origin);如果该字段存在并且为true则允许请求接口,否则禁止;
response
  • Access-Control-Allow-Origin: origin,origin表示允许哪些网站请求,不建议设置为*;
  • Access-Control-Expose-Headers:Example-Access-Control-Allow-Source-Origin,允许http返回中包含该字段,可以通过这种方式在返回头中加入自定义字段,如该例子中的Example-Access-Control-Allow-Source-Origin;