使用ajax,如果请求后端地址和页面访问的地址“URL的首部”不同就会出现访问被拒绝的情况,这就需要跨域来解决前后端的通讯问题
方法一:设置谷歌浏览器属性允许跨域
复制一个谷歌浏览器图标,右键---属性-----快捷方式tab------目标后面追加 -disable-web-security----点击应用-----点击确定
方法二(推荐):服务器反向代理解决跨域
适合大型应用的处理
指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。 这里以nginx和node来实现如下:
1 //文件nginx.conf添加代码 2 3 location ~ /api { 4 //请求后端的地址 5 proxy_pass http://www.b.com:8080; 6 }
1 //node的代理如下 2 3 proxyTable: { 4 '/api': { 5 target: 'http://www.b.com:8080/', 6 changeOrigin: true, 7 //pathRewrite: {'^/api': '/'}是否重写 8 } 9 },
说明:如果页面url为http://www.a.com的页面需要ajax请求后端http://www.b.com:8080/api/dothis.do的地址。如果设置了反向代理,即可通过http://www.a.com/api/dothis.do来获取数据,就很好的解决了跨域问题的同时并未暴露后端地址给用户。
方法三(CORS 跨域): 后端通过Access-Control-Allow-Origin来解决
适合信用度高的小型应用或者个人应用
CORS 是在 es5 之后提出的跨域方案. 只需要在服务器配置一个跨域响应头接口
Access-Control-Allow-Origin是HTML5中定义的一种解决资源跨域的策略。他是通过服务器端返回带有Access-Control-Allow-Origin标识的Response header,用来解决资源的跨域权限问题。
如果应许所有域名的访问,可以在header中设置Access-Control-Allow-Origin: * 。
如果应许部分域名访问,这里将已php为例子实现如下,这里将只应许前端URL为http://www.a.com才能访问:
1 $origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : ''; 2 $allow_origin = array( 3 'http://www.a.com', 4 ); 5 if(in_array($origin, $allow_origin)){ 6 header('Access-Control-Allow-Origin:'.$origin); 7 }
方法四:jsonp解决get请求的跨域
json是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。它的局限性主要是只支持Get
实现的思路就是:
在服务器端组装出客户端预置好的json数据,通过回调的方式传回给客户端。
这里以php为例返回如下:
1 <?php 2 $data = array();//需要返回的数据 3 $callback = $_GET['callback']; 4 echo $callback.'('.json_encode($data).')'; 5 exit; 6 ?>
前端以jquery的ajax请求为例,它封装了jsonp的实现
1 $.ajax({ 2 type : "get"//如果 3 url : "www.b.com:8080", 4 dataType : "jsonp", 5 jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名 6 success:function(json){}, 7 error:function(){} 8 });
网上找了一篇原生JS的实现,代码如下:
1 function ajax(params) { 2 params = params || {}; 3 params.data = params.data || {}; 4 var json = params.jsonp ? jsonp(params) : json(params); 5 // jsonp请求 6 function jsonp(params) { 7 //创建script标签并加入到页面中 8 var callbackName = params.jsonp; 9 var head = document.getElementsByTagName('head')[0]; 10 // 设置传递给后台的回调参数名 11 params.data['callback'] = callbackName; 12 var data = formatParams(params.data); 13 var script = document.createElement('script'); 14 head.appendChild(script); 15 //创建jsonp回调函数 16 window[callbackName] = function(json) { 17 head.removeChild(script); 18 clearTimeout(script.timer); 19 window[callbackName] = null; 20 params.success && params.success(json); 21 }; 22 //发送请求 23 script.src = params.url + '?' + data; 24 //为了得知此次请求是否成功,设置超时处理 25 if(params.time) { 26 script.timer = setTimeout(function() { 27 window[callbackName] = null; 28 head.removeChild(script); 29 params.error && params.error({ 30 message: '超时' 31 }); 32 }, time); 33 } 34 }; 35 //格式化参数 36 function formatParams(data) { 37 var arr = []; 38 for(var name in data) { 39 arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name])); 40 }; 41 // 添加一个随机数,防止缓存 42 arr.push('v=' + random()); 43 return arr.join('&'); 44 } 45 // 获取随机数 46 function random() { 47 return Math.floor(Math.random() * 10000 + 500); 48 } 49 }
CORS与jsonp相比的优点:
1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。