javascript跨域加载

server端加上header设为 Access-Control-Allow-Origin:*

header("Access-Control-Allow-Origin: *"); # 跨域处理

添加多个跨域请求域名及子域

在php下添加

if( preg_match("/http:\/\/(.*?)\.yourdomain.com/", $_SERVER['HTTP_ORIGIN'], $matches )) {
        $theMatch = $matches[0];
        header('Access-Control-Allow-Origin: ' . $theMatch);
}

或者直接在nginx下添加

location ~ \.php$ {
    # 添加子域跨域支持
   if ( $http_origin ~* (https?://(.+\.)?(syam.cc|lonal.com|coam.co)$) ) {
       add_header "Access-Control-Allow-Origin" "$http_origin";
    }
}

#注意,当$http_origin匹配到Nginx配置域名时的 add_header “Access-Control-Allow-Origin” “*”;不要笼统的设置为”*”,应像上面配置的设置特定的 $http_origin,否则浏览器能正常跨域,但像如下设置传递让浏览器传递 Cookie

$.ajax({
    url: "http://www.syam.cc/ajaxLoad/AreaSerial",
    type: "POST",
    dataType: 'json',
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true,
    success: function(json){
        //处理data数据
    }
});

浏览器还是会提示跨域错误:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://www.syam.cc/ajaxLoad/AreaSerial. This can be fixed by moving the resource to the same domain or enabling CORS.

参考 基于 Github 搭建增强版的 jekyll 博客系统 http://blog.hellofe.com/

#注意,在使用Ajax设定自定义请求头的时候,需要在Nginx的 add_header “Access-Control-Allow-Headers” 添加注册,否则浏览器同样会报错

add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,request-access-token,request-client-platform';

参考Access-Control-Allow-Origin Multiple Origin Domains? http://stackoverflow.com/questions/1653308/access-control-allow-origin-multiple-origin-domains

参考 基于 Martini 的跨域资源共享(CORS) http://se77en.cc/2014/04/09/cors-with-martini-and-golang/

参考 CORS on Nginx http://enable-cors.org/server_nginx.html

参考 Nginx CORS实现JS跨域 http://blog.csdn.net/oyzl68/article/details/18741057

参考1:解决Ajax跨域问题:Origin xx is not allowed by Access-Control-Allow-Origin. http://www.yanue.net/archives/952.html

参考2:利用CORS实现跨域请求 http://newhtml.net/using-cors/

参考 jQuery中利用JSONP解决AJAX跨域问题 http://www.clanfei.com/2012/08/1637.html

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

参考 CORS(Cross-Origin Resource Sharing) 跨域资源共享 http://www.cnblogs.com/maplejan/archive/2012/12/02/2797864.html

好了,下面进入实战,直接说说使用方法。

1 var xhr = new XMLHttpRequest();  
2 xhr.open("POST", "http://www.b.com", true);  
3 xhr.send();

没有看错!就是这么简单!

和Ajax的调用方法是毫无差异的,需要的只是服务器端的配合。

服务器端如何配置?

PHP:只需要使用如下的代码设置即可。

1 <?php  
2  header("Access-Control-Allow-Origin:*");

以上的配置的含义是允许任何域发起的请求都可以获取当前服务器的数据。

当然,这样有很大的危险性,恶意站点可能通过XSS攻击我们的服务器。

如果仅支持www.a.com这个站跨域访问,那就:

1 <?php  
2  header("Access-Control-Allow-Origin: http://www.a.com");

这样就基本配置ok了~

 

前端的部分,如果需要跨域向服务器发cookies

还需要设置一个属性:withCredentials

1 var xhr = new XMLHttpRequest();  
2 xhr.open("POST", "http://www.b.com", true);  
3 xhr.withCredentials = true; //支持跨域发送cookies
4 xhr.send();

 当然,服务器端也要设置

1 <?php
2 header("Access-Control-Allow-Credentials: true");

好吧,下面说说需要注意的地方。

如果不使用第三方库,用原生javascript来写,还是有些地方需要注意的。

1、不要设置X-Requested-With头

因为跨域访问,如需带header,服务器端必须要allow,不然报错。

setRequestHeader(“X-Requested-With”, “XMLHttpRequest”)主要用在Ajax调用资源时,服务器能判断该次请求是Ajax的。

2、INVALID_STATE_ERR: DOM Exception 11

这是一个神奇的错误,网上找了一下,也没什么较为明确的答复。但我却在手机端遇到了这个问题!

测试了一下:在IOS4和IOS5的UC浏览器、Safari、Chrome,进行CORS访问均会报这个错,

Android4.0原生浏览器,也无法正常CORS(没有测试2.3和2.2)

估计也是报这个错,但没控制台,所以无法查bug。

Android4.0下的Chrome和UC都可以顺利CORS。

本以为是浏览器兼容的问题,经过蛋疼的排查之后,发现…

我们可以看一下,下面两段代码有啥差异?

1 var xhr = new XMLHttpRequest();  
2 xhr.withCredentials = true; //支持跨域发送cookies
3 xhr.open("POST", "http://weibo.com/demo/b/index.php", true);  
4 xhr.send();
1 var xhr = new XMLHttpRequest();  
2 xhr.open("POST", "http://weibo.com/demo/b/index.php", true);  
3 xhr.withCredentials = true; //支持跨域发送cookies
4 xhr.send();

唯一的差异就是xhr.withCredentials = true; 的位置。

但就是这个差别,导致第一段代码无法顺利在手机端运行,并报INVALID_STATE_ERR: DOM Exception 11这个错!

而在桌面版浏览器下,两段代码都可以顺利运行!

所以,以后设置withCredentials属性时,一定要在open方法之后!

Leave a Comment

电子邮件地址不会被公开。 必填项已用*标注