ajax跨域问题完美解决

背景:今天被问到,不会答,好久没有用到,瞬间感觉自己好菜,有点不爽,之前配过nginx的,然后面试官还叫我找出这个文章,日记存在企鹅空间的,半天没找出来那篇文章,然后被面试过鄙视了,回来赶紧搜索一下。
下面是查找到的答案,然后自己测试通过,下次再问我,我就搬这边文章出来给他看。
什么是跨域?

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。

所谓同源是指,域名,协议,端口均相同,不明白没关系,举个栗子:

http://www.123.com/index.html 调用 http://www.123.com/server.php (非跨域)

http://www.123.com/index.html 调用 http://www.456.com/server.php (主域名不同:123/456,跨域)

http://abc.123.com/index.html 调用 http://def.123.com/server.php (子域名不同:abc/def,跨域)

http://www.123.com:8080/index.html 调用 http://www.123.com:8081/server.php (端口不同:8080/8081,跨域)

http://www.123.com/index.html 调用 https://www.123.com/server.php (协议不同:http/https,跨域)

请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。
浏览器执行javascript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。
跨域有:
1.不同域名肯定是跨域了
2.admin.xx.com/www.xx.com同域名,子域名不同跨域,
3.同域名不同端口跨域
**

解决办法:1、加header头接收所有请求:

**
首先在本地配置两个域名:
host文件加上这两行
127.0.0.1 www.dd.com
127.0.0.1 www.abc.com
nginx server 1

server{
        listen       80;
        server_name  www.abc.com;
        root   "D:/phpStudy/WWW/abc";
        location / {
            index  index.php index.htm /public/index.html;
           autoindex  off;
        }
        location ~ \.php(.*)$  {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO  $fastcgi_path_info;
            fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
            include        fastcgi_params;
        }
    }

nginx server 2

server {
        listen       80;
        server_name  www.dd.com;
        root   "D:/phpStudy/WWW/ddpay";
        location / {
            index  index.php index.htm /public/index.html;
           autoindex  off;
        }
        location ~ \.php(.*)$  {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO  $fastcgi_path_info;
            fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
            include        fastcgi_params;
        }
    }

ajax跨域请求的服务端代码:
就是接收一段请求返回一段json字符串的意思,这个大家都懂的

 public function  hey(){
        header('Access-Control-Allow-Origin:*');//允许所有来源访问
        header('Access-Control-Allow-Method:POST,GET');//允许访问的方式
        $data = I('postData');
        $response['msg'] = "i get it . are you ok? ".$data;
        echo json_encode($response);
        exit();//这里一定要加上exit,不然你会怀疑人生的!
    }

//ajax跨域abc.com发起ajax请求代码:

    $("#test_ajax").click(function(){
            var postData = "halou ,guy!";
            $.post('http://www.dd.com/index.php/Home/mall/hey',{'postData':postData},function(data){
                alert(data.msg);
            });

        });

服务端响应完毕如果不加exit()退出,会返回json字符串和一堆没用的东西,在客户端那边看着就一脸懵逼了,一定要加上去,不然某些框架还会继续有其他操作的

2. jsonp解决,但只支持get请求,不支持Post请求

网上搜索了2小时………. IE10-以下不兼容,算!!!!

3.NGINX代理方式处理请求

nginx反向代理实现跨域
上面提到的这些跨域方法,都有一些问题。有的不能支持所有浏览器,有的需要修改javascript代码,有的需要重写服务器端代码。有的在session等场景下会有问题。

其实,用nginx反向代理实现跨域,是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,并且不会影响服务器性能。
我们只需要配置nginx,在一个服务器上配置多个前缀来转发http/https请求到多个真实的服务器即可。这样,这个服务器上所有url都是相同的域名、协议和端口。因此,对于浏览器来说,这些url都是同源的,没有跨域限制。而实际上,这些url实际上由物理服务器提供服务。这些服务器内的javascript可以跨域调用所有这些服务器上的url。

下面,给出一个nginx支持跨域的例子,进行具体说明。
如,我们有两个pythonflask开发的项目:testFlask1和testFlask2。
testFlask2项目上的javascript脚本要通过ajax方式调用testFlask1的一个url,获取一些数据。
正常情况下部署,就会有跨域问题,浏览器拒绝执行如下这样的调用。

$("button").click(function(){
   $.get("127.0.0.1:8081/partners/json",
   function(result){
      $("div").html(result);
   });
});

下面把testFlask2项目的javascrip文件修改一下。这样访问同源的url,就不会有跨域问题。

$("button").click(function(){
    $.get("partners/json",
    function(result){
     $("div").html(result);
    });
});

但是,我们testFlask2项目实际上没有partners/json这样的url,那怎么处理呢?

server{
listen8000;
location/ {
includeuwsgi_params;

uwsgi_passunix:/tmp/testFlask2.sock;
}
location/partners {
rewrite^.+partners/?(.*)$ /$1 break;
includeuwsgi_params;

uwsgi_passunix:/tmp/testFlask1.sock;
}

}

我们把testFlask2项目部署在8080端口的根目录下。把提供web服务的testFlask1项目部署在/partners目录下。

但我们的testFlask1项目并不能处理/partners/json这样的url请求。那怎么办呢?

通过 rewrite^.+partners/?(.)/ 1 break; 这一条命令,nginx可以把收到的/partners/请求全部转为/*请求后再转发给背后的真实web服务器。

这样,RESTFUL的ajax客户端程序,只需要给出特定前缀的url就可以调用任意服务器提供的RESTFUL接口了。

甚至,通过nginx的反向代理,我们还能调用其他公司开发的网站提供的RESTFUL接口。

如,

location/sohu {
rewrite^.+sohu/?(.*)$ /$1 break;
includeuwsgi_params;

proxy_passhttp://www.sohu.com/;
}

我们就把sohu网站整个搬到我们的8080:/sohu/目录下了,我们的javascript就可以尽情调用其RESTFUL服务了。

顺便说一下,rewrite^.+sohu/?(.*)/ 1 break; 这句命令中,1(.)() 1,第二对()内的参数就是$2,以此类推。
通过把本地一个url前缀映射到要跨域访问的web服务器上,就可以实现跨域访问。

对于浏览器来说,访问的就是同源服务器上的一个url。而nginx通过检测url前缀,把http请求转发到后面真实的物理服务器。并通过rewrite命令把前缀再去掉。这样真实的服务器就可以正确处理请求,并且并不知道这个请求是来自代理服务器的。

简单说,nginx服务器欺骗了浏览器,让它认为这是同源调用,从而解决了浏览器的跨域问题。又通过重写url,欺骗了真实的服务器,让它以为这个http请求是直接来自与用户浏览器的。

我们这样编写nginx的配置文件:
原文地址:http://blog.csdn.net/lambert310/article/details/51683775
其他参考地址好多好多好多…..

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章