深入剖析jsonp跨域原理

在项目中遇到一个jsonp跨域的问题,于是仔细的研究了一番jsonp跨域的原理。搞明白了一些以前不是很懂的地方,比如:

1)jsonp跨域只能是get请求,而不能是post请求;

2)jsonp跨域的原理到底是什么;

3)除了jsonp跨域之外还有那些方法绕过“同源策略”,实现跨域访问;

4)jsonp和ajax,或者说jsonp和XMLHttpRequest是什么关系;

等等。

1.同源策略

说到跨域,首先要明白“同源策略”。同源是指:js脚本只能访问或者请求相同协议,相同domain(网址/ip),相同端口的页面。

我们知道,js脚本可以访问所在页面的所有元素。通过ajax技术,js也可以访问同一协议,同一个domain(ip),同一端口的服务器上的其他页面,请求到浏览器端之后,利用js就可以进行任意的访问。但是对于协议不同, 或者domain不同或者端口不同的服务器上的页面就无能为力了,完全不能进行请求。

下面在本地搭建两个tomcat,分别将端口设为8080,和8888,进行相关实验。显然他们的端口是不同的。演示如下:

http://localhost:8888/html4/ajax.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

32

33

34

35

36

37

38

39

40

doctype html>

<html>

<head>

    <meta charset="utf-8">

    <meta name="keywords" content="jsonp">

    <meta name="description" content="jsonp">

    <title>jsonptitle>

    <style type="text/css">

        *{margin:0;padding:0;}

        a{display:inline-block;margin:50px 50px;}

    style>

head>

<body>

    <a href="javascript:;" onclick="myAjax();">click mea>

     

<script type="text/javascript" src="js/jquery-1.11.1.min.js">script>

<script type="text/javascript">

function myAjax(){

    var xmlhttp;

    if(window.XMLHttpRequest){

        xmlhttp = new XMLHttpRequest();

    }else{

        xmlhttp = ActionXObject("Microsoft.XMLHTTP");

    }

     

    xmlhttp.onreadystatechange = function(){

        if (xmlhttp.readyState==4 && xmlhttp.status==200){

            console.log(xmlhttp.responseText);         

        }

    }

    var url = "http://localhost:8080/minisns/json.jsp" + "?r=" + Math.random();

    xmlhttp.open("Get", url, true);

    xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");

    xmlhttp.send();

}

script>

body>

html>

这里为了结果不受其他js库的干扰,使用了原生的XMLHttpRequest来处理,结果如下:

深入剖析jsonp跨域原理_第1张图片

我们看到8080端口的js的ajax请求无法访问8888端口的页面。原因是“同源策略不允许读取”。

既然普通的ajax不能访问,那么怎样才能访问呢?大家都知道,使用jsonp啊,那jsonp的原理是什么呢?他为什么能跨域呢?

2.jsonp跨域的原理

我们知道,在页面上有三种资源是可以与页面本身不同源的。它们是:js脚本,css样式文件,图片,像taobao等大型网站,很定会将这些静态资源放入cdn中,然后在页面上连接,如下所示,所以它们是可以链接访问到不同源的资源的。

1)

2)

3)

而jsonp就是利用了

复制代码

访问结果如下:

深入剖析jsonp跨域原理_第9张图片

5. 参数jsonp 和 jsonpCallback

jsonp指定使用哪个名字将回调函数传给服务端,也就是在服务端通过 request.getParameter(""); 的那个名字,而jsonpCallback就是request.getParamete("")取得的值,也就是回调函数的名称。其实这两个参数都可以不指定,只要我们是通过 success : 来指定回调函数的情况下,就可以省略这两个参数,jsnop如果不知道,默认是 "callback",jsnpCallback不指定,是jquery自动生成的一个函数名称,其对应源码如下:

1

2

3

4

5

6

7

8

9

10

11

12

var oldCallbacks = [],

    rjsonp = /(=)\?(?=&|$)|\?\?/;

// Default jsonp settings

jQuery.ajaxSetup({

    jsonp: "callback",

    jsonpCallback: function() {

        var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );

        this[ callback ] = true;

        return callback;

    }

});

你可能感兴趣的:(javascript)