Ajax跨域与解决方案

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ajax跨域与解决方案相关的知识,希望对你有一定的参考价值。

1.同步交互与异步交互

同步交互:用户在URL地址输入http://www.baidu.com,服务器接收请求并进行相应处理,此时用户无法操作,只能等待,只有当返回数据到客户端的时候,用户才能继续操作
异步交互:用户操作某个页面,请求某个数据,客户可以继续操作(服务器返回数据),不涉及到整个页面的刷新

2.XmlHttp

XmlHttp是一套可以在javascript、VbScript、Jscript等脚本语言中通过http协议传送或从接收XML及其他数据的一套API。XmlHttp最大的用处是可以更新网页的部分内容而不需要刷新整个页面

3.ajax demo (理解ajax)  

文件有两个1.html和1.php

1.html代码如下

 1 <!DOCTYPE html>  
 2 <html lang="en">  
 3 <head>  
 4     <meta charset="UTF-8">  
 5     <title>Document</title>  
 6 </head>  
 7 <body>  
 8     <input type="button" value="ajax" id="ajax" />  
 9     <div id="msg"></div>  
10 </body>  
11 <script>  
12     var button = document.getElementById(ajax);  
13     button.onclick = function() {  
14         //创建XmlHttp对象  
15         var xhr = new XMLHttpRequest();  
16         //创建请求  
17         xhr.open(post,1.php);  
18         //如果需要像HTML表单那样POST数据,请使用 setRequestHeader()来添加HTTP头,如果不添加这一行代码php接受不到post数据  
19         xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");  
20         //发送请求到http服务器  
21         xhr.send(username=yaxian&age=18);  
22         //当XMLHTTPRequest对象的readyState属性改变时的事件处理句柄  
23         xhr.onreadystatechange = function() {  
24             //返回XMLHTTP请求的当前状态 4代表数据接受完毕  
25             if(xhr.readyState == 4) {  
26                 //返回当前请求的http状态码 200代表OK  
27                 if(xhr.status == 200) {  
28                     //将响应信息作为字符串返回  
29                     var data = xhr.responseText;  
30                     document.getElementById(msg).innerHTML = data;  
31                 }  
32             }  
33         }  
34     }  
35 </script>  
36 </html>

1.php代码如下

1 <?php  
2     echo ‘php data : ‘.$_POST[‘username‘].$_POST[‘age‘];
3 ?>

结果是:

技术分享

4.Ajax跨域是什么

 

我们先回顾一下域名地址的组成:

http:// www . google : 8080 / script/jquery.js

      http:// (协议号)

               www  (子域名)

             google (主域名)

               8080 (端口号)

script/jquery.js (请求的地址)

* 当协议、子域名、主域名、端口号中任意一各不相同时,都算不同的“域”。

* 不同的域之间相互请求资源,就叫“跨域”。

比如:http://www.abc.com/index.html 请求 http://www.def.com/sever.php

 

由于在工作中需要使用AJAX请求其他域名下的请求,但是会出现拒绝访问的情况,这是因为基于安全的考虑,AJAX只能访问本地的资源,而不能跨域访问。比如说你的网站域名是aaa.com,想要通过AJAX请求bbb.com域名中的内容,浏览器就会认为是不安全的,所以拒绝访问

5.解决方案

方案1 jsonp

JSONP是JSON格式的扩展.如果指定了script或者jsonp类型,那么当从服务器接收到数据时,实际上是用了<script>标签而不是XMLHttpRequest对象。这种情况下,$.ajax()不再返回一个XMLHttpRequest对象,并且也不会传递事件处理函数,比如beforeSend。

jsonp有什么用:由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求

html代码如下(使用jquery):

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Document</title>
 6     <script type="text/javascript" src="jquery.js"></script>
 7 </head>
 8 <body>
 9     <input type="text" id="telephone" />
10     <button id="ajax">提交</button>
11 </body>
12 <script>
13     $(function() {
14         var ajax = $(#ajax);
15         //$.ajax是jquery封装方法,底层还是使用XMLHttpRequest发送请求,还是有跨域限制
16         ajax.click(function() {
17             var telephone = $(#telephone).val();
18             
19             $.ajax({
20                 type        : get,
21                 url         : http://api.jisuapi.com/shouji/query,
22                 data        : appkey=yourappkey&shouji=+telephone,
23                 dataType    : jsonp,
24                 success:function(msg){
25                 console.log(msg);
26                 }
27             });
28         });
29     });
30 </script>
31 </html>

结果:

技术分享

若注释dataType:‘jsonp‘这一行代码结果如下:(提示跨域导致请求失败)

html代码如下(原生js,不使用jquery)

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Document</title>
 6 </head>
 7 <body>
 8     <button id="ajax">通过script标签发送请求</button>
 9 </body>
10 <script>
11 /*
12     因为服务器返回的数据格式是{"username":"yaxian", "age":18},客户端以js语法无法解析
13     所以客户端需要给服务器传递一个回调函数,服务器返回一个回调函数的调用,并将服务端数据包含在这个函数调用里面
14     这样客户端得到的是这样的数据getInfo({"username":"yaxian", "age":18}),js解析后会调用getInfo函数
15     这种方式只能解决get方式跨域,因为script标签发送请求是get请求
16 */
17     var ajax = document.getElementById(ajax);
18     function getInfo(obj) {
19         console.log(obj);
20     }
21     ajax.onclick = function() {
22         var script = document.createElement(script);
23         //callback是跨域通用的参数名称
24         script.src = http://test.com/1.php?callback=getInfo;
25         document.body.appendChild(script);
26     }
27 </script>
28 </html>

php代码如下 

1 <?php 
2     //接受callback(必须是get方式)
3     $callback = $_GET[‘callback‘];
4     //getInfo({"username":"yaxian", "age":18});
5     echo $callback.‘({"username":"yaxian", "age":18})‘;    
6  ?>

结果:

技术分享

方案2  jsonp是get形式,承载的信息量有限,所以信息量较大时CORS是不二选择

6.实例(跨域请求360搜索接口)

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Document</title>
 6     <style>
 7         .msg{
 8             border:1px solid #ccc;
 9             margin-left:-53px;
10             border-top:none;
11             display:none;
12         }
13         ul{
14             margin:0;
15             padding:0;
16             list-style:none;
17         }
18         .w500{
19             width:500px;
20         }
21         li{
22             padding:5px;
23             cursor:pointer;
24         }
25     </style>
26     <script src="jquery.js"></script>
27 </head>
28 <body>
29     <div align="center">
30         <input type="text" class="keywords w500" id="keywords" />
31         <input type="button" value="搜索" />
32         <div class="msg w500" align="left" id="msg">
33             <ul id="list">
34                 <!-- 
35                     <li>中国好声音</li>
36                     <li>中国666</li>
37                     <li>中国王胜涛</li> 
38                 -->
39             </ul>
40         </div>
41     </div>
42 </body>
43 <script>
44     function getInfo(obj) {
45         //如果直接给li绑定事件获取不到li元素,使用jquery事件委托
46         $(#msg).on(mouseover, li, function() {
47             this.style.background = "#ccc";
48         });
49         $(#msg).on(mouseout, li, function() {
50             this.style.background = "";
51         });
52 
53         //解析数据
54         var result = obj.result;
55         document.getElementById(list).innerHTML = ‘‘;
56         for(var i = 0; i < result.length; i++) {
57             var li = document.createElement(li);
58             li.innerHTML = result[i].word;
59             document.getElementById(list).appendChild(li);
60         }
61     }
62     document.getElementById(keywords).onkeyup = function() {
63         var keywords = this.value;
64         if(keywords.length>0) {
65             //显示提示区域
66             document.getElementById(msg).style.display = block;
67             //使用script标签发送请求
68             var script = document.createElement(script);
69             script.src = https://sug.so.360.cn/suggest?callback=getInfo&encodein=utf-8&encodeout=utf-8&format=json&fields=word,obdata&word=+keywords;
70             document.body.appendChild(script);
71         } else {
72             //隐藏提示区域
73             document.getElementById(msg).style.display = none;
74         }
75     }
76 </script>
77 
78 </html>

 

结果:

技术分享

 


以上是关于Ajax跨域与解决方案的主要内容,如果未能解决你的问题,请参考以下文章

AJAX的跨域与JSONP

跨域与防止表单重复提交

CORS跨域与Nginx反向代理跨域优劣对比

CORS跨域与Nginx反向代理跨域优劣对比

ajax跨域请求

跨域问题的产生及解决方法