PHP 浏览器跨域安全

一、什么是跨域

跨域:由于浏览器的同源策略,即属于不同域的页面之间不能相互访问各自的页面内容。详细见下表:

注:同源策略,单说来就是同协议,同域名,同端口

二、为什么要跨域

出于安全考虑(比如csrf攻击),浏览器一般会禁止进行跨域访问,但是因为有时有相应需求,需要允许跨域访问,这时,我们就需要将跨域访问限制打开。

比如:Ajax请求另一个域名获取数据

当前网站www.kk.com 请求另一网站接口 www.oo.com/getuser/uid/220305, 获取user数据

三、跨域的实现

1、前后端结合(JsonP)

虽然jsonp也可以实现跨域,但是因为jsonp不支持post请求,应用场景受到很大限制,所以这里不对jsonp作介绍。

了解jsonp实现跨域可以点击这里:

https://blog.csdn.net/u014607184/article/details/52027879/

2、纯后端方式一(CORS方式)

CORS 是w3c标准的方式,通过在web服务器端设置:响应头Access-Cntrol-Alow-Origin 来指定哪些域可以访问本域的数据,ie8&9(XDomainRequest),10+,chrom4,firefox3.5,safair4,opera12支持这种方式。

服务器代理,同源策略只存在浏览器端,通过服务器转发请求可以达到跨域请求的目的,劣势:增加服务器的负担,且访问速度慢。

这种方式直接在响应php文件中设置header即可

示例代码:

<?php
header('Access-Control-Allow-Origin:http://www.kk.com');
$data = array(
    'name'=>'m_nanle_xiaobudiu',
    'age'=>26,
    'sex'=>'man'
);
echo json_encode($data);

当我们需要允许多个域名跨域访问时,可以这样做

<?php
$origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '';

$allow_origin = array(
    'http://www.kk.com',
    'http://www.gg.com'
);

if(in_array($origin, $allow_origin)){
    header('Access-Control-Allow-Origin:'.$origin);
}
$data = array(
    'name'=>'m_nanle_xiaobudiu',
    'age'=>26,
    'sex'=>'man'
);
echo json_encode($data);

3、纯后端方式二(Nginx代理方式)【建议这种方式】

直接在nginx服务器上设置模块参数。

—— 代码实现:

 html部分(www.kk.com):

<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>测试ajax和跨域访问</title>
    <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
</head>
<script type="text/javascript">
    $(document).ready(function(){
        $.ajax({
            type: "post",
            url: "http://www.oo.com/1.php",
            success: function(data) {
                alert(data);
            },
            error: function() {
                alert("fail!!!,请刷新再试!");
            }
        });
    });
</script>
<body>
<h1>测试跨域访问</h1>
</body>
</html>

php部分(www.oo.com):

<?php
$data = array(
    'name'=>'m_nanle_xiaobudiu',
    'age'=>26,
    'sex'=>'man'
);
echo json_encode($data);

Nginx配置文件部分、

server {

        listen       80;
        server_name  www.oo.com ;
        root   "G:\oo";

        add_header Access-Control-Allow-Origin http://www.kk.com;
        add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;

        location / {
            index  index.html index.htm index.php;
            #autoindex  on;
        }

        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;
        }
}

注:实际项目中,可能我们提供的接口需要允许不止一个域名访问,这时,我们需要配置允许多个域名访问,这时,我们可以用map

示例:

map $http_origin $corsHost {
    default 0;
    "~http://www.kk.com" http://www.kk.com;
    "~http://www.gg.com" http://www.gg.com;
}
server {
        listen       80;
        server_name  www.oo.com ;
        root   "G:\oo";
        add_header Access-Control-Allow-Origin $corsHost;
        add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
        location / {
            index  index.html index.htm index.php;
            #autoindex  on;
        }
        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;
        }
}