跨域请求

跨域的相关概念

当请求访问其他服务器的数据时,客户端会出现跨域问题

跨域问题是由于javascript语言安全限制中的同源策略造成的

简单来说,同源策略是指一段脚本只能读取来自同一来源的窗口和文档的属性,这里的同一来源指的是主机名、协议和端口号的组合

URL 说明  通信 

http://www.a.com/a.js

http://www.a.com/b.js

 同一域名  允许
 

http://www.a.com/file/a.js

http://www.a.com/lib/b.js

 同一域名

不同文件夹

 允许
 

http://www.a.com:8080/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://59.65.233.233/b.js

域名IP

 不允许
 

http://www.a.com/a.js

http://script.a.com/b.js

主域相同

子域不同

 不允许
 

http://www.a.com/a.js

http://www.different.com/b.js

不同域名  不允许

跨域的例子:

在tomcat6中部署了项目TestA,在tomcat7中部署了项目TestB(tomcat6的端口改为8081)

TestA中的index.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
  <head>    
    <title>A</title>    
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
  </head>  
  <body>
    This is my A page. <br>
    </script>
<script type="text/javascript">  
            function sayHello(a){  
                alert('B.word is ' + a);  
            }
            $.getJSON('http://localhost:8080/TestB/index.jsp', function(data){  
                sayHello(data);  
            });
    </script>  
  </body>
</html>

于是出现如下错误:

 

解决方法

1.<script>标签及jsonp

 浏览器会阻止ajax请求非同源的内容,但没有限制<script>标签来访问非同源的内容,也没有限制使用动态添加<script>标签,所以可以采用这种方式打破这种限制。

TestA中index.jsp:

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <!DOCTYPE HTML>
 3 <html>
 4     <head>    
 5      <title>A</title>    
 6      <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
 7    </head>  
 8    <body>
 9      This is my A page. <br>
10      <script type="text/javascript" src="http://localhost:8080/TestB/index.jsp"></script>
11      <script type="text/javascript">  
12      function sayHello(){  
13          alert('B.word is ' + a);  
14      }
15      sayHello();
16      </script>  
17    </body>
18  </html>

TestB中index.jsp:

 <%
String str="test1";
out.println("var a = '"+str+"';");  //返回值
%>

解释:

第10行,利用<script>标签请求到了TestB中的资源,请求返回是一个js文件,这个js的内容就是“var a='test1'”,因此在第15行调用sayHello()时能够获取到a的值

改进:

尤其,我们利用动态生成<script>标签的方法来实现动态跨域请求 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
  <head>    
    <title>A</title>    
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
    <script type="text/javascript">  
    window.onload = function (){  
        var scriptBlock = document.createElement("script");
         scriptBlock.src = "http://localhost:8080/TestB/index.jsp";
         scriptBlock.type = "text/javascript";
         scriptBlock.language = "javascript";         
         document.getElementsByTagName("head")[0].appendChild(scriptBlock); 
         //setTimeout(sayHello,1000);//延时执行
         scriptBlock.onload=sayHello;
    } 
    function sayHello(){
        if(document.readyState=="complete")
            alert('B.word is ' + a); 
    }
    </script>  
  </head>  
  <body>
    This is my A page. <br>
  </body>
</html>

注:因为chrome不支持onreadystatechange,所以改用onload在IE和Chrome下都能运行

同样通过延时执行也能弹出结果,但是并不妥当。

利用jquery获取JSONP:

JSONP(JSON with Padding)就是服务器端和客户端互相协作以完成跨域请求的一种协议,客户端向服务器端发送请求并附带callback函数,服务器端返回相应的js代码,这个代码就是执行回调函数,参数就是服务器端返回的JSON数据。
客户端在发起跨域请求时,需要制定具体的回调函数,callback就是回调函数,服务器端也要通过callback要提取回调函数名,所以具体的这个参数需要客户端和服务器端达成一致,否则不能实现跨域。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
  <head>    
    <title>A</title>    
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
    <script type="text/javascript">  
    function sayHello(data){
        alert(data.Email)
   }
    $.ajax({
        url: 'http://localhost:8080/TestB/somejson.json',
        dataType: "jsonp",
        jsonp: "callback"
    })
    </script>  
  </head>  
  <body>
    This is my A page. <br>
  </body>
</html>

其中somejson.json文件:

sayHello({"Email":"jellybaobao@139.com"})

 

 

posted @ 2014-09-26 14:03  苜冉冉  阅读(182)  评论(0编辑  收藏  举报