一、什么是跨域
跨域:由于浏览器的同源策略,即属于不同域的页面之间不能相互访问各自的页面内容。详细见下表:
注:同源策略,单说来就是同协议,同域名,同端口
URL | 说明 | 是否允许通信 |
---|---|---|
http://www.a.com/a.js http://www.a.com/b.js |
同一域名下 | 允许 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同一域名下不同文件夹 | 允许 |
http://www.a.com:8000/a.js http://www.a.com/b.js |
同一域名,不同端口 | 不允许 |
http://www.a.com/a.js https://www.a.com/b.js |
同一域名,不同协议 | 不允许 |
http://www.a.com/a.js http://70.32.92.74/b.js |
域名和域名对应ip | 不允许 |
http://www.a.com/a.js http://script.a.com/b.js |
主域相同,子域不同 | 不允许 |
http://www.a.com/a.js http://a.com/b.js |
同一域名,不同二级域名(同上) | 不允许(cookie这种情况下也不允许访问) |
http://www.cnblogs.com/a.js http://www.a.com/b.js |
不同域名 | 不允许 |
二、为什么要跨域
出于安全考虑(比如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; } }