之前遇到过跨域的问题,一直觉得很神秘,也没有多关注,就过去了,今天又看到几篇文章说跨域,闲来无事于是将其整理记录下来;
一些概念
先来阐述下几个概念:
 
跨域:是指浏览器对于JavaScript的同源策略限制,只要协议、域名、端口有任何一个不同,都被当作是不同的域,都不能执行或获取其他网站的资源;
姑且这么定义吧,举个简单例子,就是www.client.com网站上的程序不能从www.server.com网站上获取数据,如果强行获取,则会报出下面错误

有没有跨域,判断是不是属于跨域,可以参考下面:
CORS:CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通.CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败.
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的.如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问.
解决方法
Solution 1:服务端程序解决
如果是双方预定沟通好请求允许数据,可以在服务端添加header头来解决
1 2 3
   | header( "Access-Control-Allow-Origin:*" );
  header( "Access-Control-Allow-Methods:POST,GET" );
   | 
 
看下面的例子:
客户端 www.client.com/cliend.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
   | 
  <!DOCTYPE html> <html> <head>     <meta http-equiv="content-type" content="text/html;charset=utf-8">     <title> 跨域测试 </title>     <script src="//code.jquery.com/jquery-1.11.3.min.js"></script> </head>
  <body> <button style="width:100px">click client</button> <script type="text/javascript">     $("button").click(function () {         $.ajax({             url: "http://www.server.com/server.php",             type: "post",             data: {'text': 'hello world'},             success: function (msg) {                 $("button").html(msg);             }
          });     }); </script> </body> </html>
 
  | 
 
服务器端 www.server.com/server.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
   | //允许所有域名获取数据 <?php $text = $_POST['text']; //允许所有的域名 header('content-type:application:json;charset=utf8'); header('Access-Control-Allow-Origin:*');   header('Access-Control-Allow-Methods:POST,GET');   header('Access-Control-Allow-Headers:x-requested-with,content-type'); echo json_encode($text); ?>
  //允许制定域名获取数据 <?php $text = $_POST['text']; header('content-type:application:json;charset=utf8'); $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : ''; //允许指定域名 $allow_origin = [     'http://www.client.com',     'http://www.client2.com' ]; if (in_array($origin, $allow_origin)) {     header('Access-Control-Allow-Origin:' . $origin);     header('Access-Control-Allow-Methods:POST,GET');     header('Access-Control-Allow-Headers:x-requested-with,content-type'); } echo json_encode($text); ?>
   | 
 
这样,理论上就可以解决跨域问题:

Solution 2:代理模式
解决思路:
例如 www.client.com/client.html 需要调用 www.server.com/server.php ,可以写一个接口 www.client.com/server.php ,由这个接口在后端去调用 www.server.com/server.php 并拿到返回值,然后再返回给index.html,这就是一个代理的模式.相当于绕过了浏览器端,自然就不存在跨域问题.
Solution 3:使用JSONP
使用之前,建议去看下我的另一篇文章Json和JsonP,然后再过来实践;
还是直接上代码:
客户端 www.client.com/client.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
   | <!DOCTYPE html> <html> <head>     <meta http-equiv="content-type" content="text/html;charset=utf-8">     <title> 跨域测试 </title>     <script src="//code.jquery.com/jquery-1.11.3.min.js"></script> </head>
  <body> <button id="clickMe" style="width:100px">click get jsonP</button> <script type="text/javascript">     $("#clickMe").click(function () {         $.ajax({             url: "http://www.server.com/jsonP.json",             type: "post",             dataType: "jsonP",             data: {'text': 'hello world'},             jsonpCallback: 'returnData',  //可自定义 函数名             success: function (msg) {                 alert(msg.text);             },             error: function (XMLHttpRequest, textStatus, errorThrown) {                 alert(XMLHttpRequest.status);                 alert(XMLHttpRequest.readyState);                 alert(textStatus);             }         });     }); </script> </body> </html>
   | 
 
服务器端 www.server.com/jsonP.json
1
   | returnData({"text":"hello jsonP"});
  | 
 
同样的也可以跨域获取数据
客户端 www.client.com/client.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Document</title> </head> <body> <iframe style="display: none" src="http://www.server.com/server.html" name="postIframe" onload="messageLoad()"></iframe> <script>     function messageLoad() {         var url = "http://www.server.com";         window.postIframe.postMessage("给我tsort的信息", url); //发送数据     }     window.onmessage = function (e) {         e = e || event;         console.log(e.data); //接收b返回的数据,在控制台有两次输出     } </script> </body> </html>
   | 
 
服务器端 www.server.com/server.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   | <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Document</title> </head> <body> <script>     window.onmessage = function(e){         e = e || event;         alert(e.data); //立即弹出a发送过来的数据         e.source.postMessage("好的,请稍等三秒!",e.origin); //立即回复a
          var postData = {name:"tsrot",age:24};         var strData = JSON.stringify(postData); //json对象转化为字符串         setTimeout(function(){             e.source.postMessage(strData,e.origin);         },3000); //3秒后向a发送数据     } </script> </body> </html>
   |