加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

跨域之JSONP

发布时间:2020-12-16 18:51:14 所属栏目:百科 来源:网络整理
导读:1 跨域及同源策略 1.1 什么是跨域 一般来说,如果你在开发中需要进行跨域操作(从一个非同源网站发送请求获取数据),一般而言,你在浏览器控制台看到的结果为: XMLHttpRequest cannot load http://external-domain/service. No ‘Access-Control-Allow-Ori

1 跨域及同源策略

1.1 什么是跨域

一般来说,如果你在开发中需要进行跨域操作(从一个非同源网站发送请求获取数据),一般而言,你在浏览器控制台看到的结果为:

XMLHttpRequest cannot load http://external-domain/service. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://my-domain’ is therefore not allowed access.

像这样发送ajax请求会在浏览器中得到如下访问受限的提示

<html>
<head>
<meta charset="utf-8" />
<script>
function success(text) {
var textarea = document.getElementById('test-response-text');
textarea.innerHTML = text;
}

function fail(code) {
var textarea = document.getElementById('test-response-text');
textarea.innerHTML = 'Error code: ' + code;
}

function helloAjax() {
var request = new XMLHttpRequest(); // 新建XMLHttpRequest对象

request.onreadystatechange = function () { // 状态发生变化时,函数被回调
if (request.readyState === 4) { // 成功完成
    // 判断响应结果:
    if (request.status === 200) {
        // 成功,通过responseText拿到响应的文本:
		//alert('request.responseText');
        return success(request.responseText);
    } else {
        // 失败,根据响应码判断失败原因:
		//alert('request.status');
        return fail(request.status);
    }
} else {
    console.log('continuing……');
}
}

// 发送请求:
request.open('GET','http://api.money.126.net/data/feed/0000001,1399001,1399006?callback=refreshPrice');
request.send();

alert('请求已发送,请等待响应...');
}

</script>
</head>
<body>
<div>
<p id="test-response-text"></p>
<p><button type="button" onclick="helloAjax()">刷新</button></p>
</div>
</body>
</html>

1.2 同源策略

说到跨域就不得不提“同源策略”。同源策略是Web浏览器针对恶意的代码所进行的措施,为了防止世界被破坏,为了保护世界的和平,Web浏览器,采取了同源策略,只允许脚本读取和所属文档来源相同的窗口和文档的属性。那么,怎么判断文档来源是否相同呢?很简单,看三个部分: 协议主机端口号。只要其中一个部分不同,则不同源。

1.3 跨域的应用场景

  1. 来自 home.example.com 的文档里的脚本读取 developer.example.com载入的文档的属性。

  2. 来自 home.example.com 的文档里的脚本读取 text.segmentfault.com载入的文档的属性

2 JSONP跨域

实际应用场景中不可避免地需要进行跨域操作,这时候“同源策略”就显得过于苛刻。JSONP跨域GET请求是一个常用的解决方案。

2.1 概念介绍

JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求, 我们可以通过使用html的script标记来进行跨域请求(即利用在页面中创建<script>节点的方法向不同域提交HTTP请求),并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。 这种跨域的通讯方式称为JSONP。

假设在http://example1.com/index.php这个页面中向http://example2.com/getinfo.php提交GET请求,我们可以将下面的JavaScript代码放在http://example1.com/index.php这个页面中来实现:

当GET请求从http://example2.com/getinfo.php返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用http://example1.com/index.php页面中的一个callback函数。

2.2 原理及实例

JSONP的最基本的原理是:

动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。这样说来,这种跨域方式其实与ajax XmlHttpRequest协议无关了。

这样其实"jQuery AJAX跨域问题"就成了个伪命题,jquery $.ajax方法名有误导人之嫌。如果设为dataType: 'jsonp',这个$.ajax方法就和ajax XmlHttpRequest没什么关系了,取而代之的则是JSONP协议。JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。

Jsonp的执行过程如下:

首先在客户端注册一个callback (如:'jsoncallback'),然后把callback的名字(如:jsonp1236827957501)传给服务器。注意:服务端得到callback的数值后,要用jsonp1236827957501(......)把将要输出的json内容包括起来,此时,服务器生成 json 数据才能被客户端正确接收。

然后以 javascript 语法的方式,生成一个function, function 名字就是传递上来的参数 'jsoncallback'的值 jsonp1236827957501 .

最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。

例1:

<html>
<head>
<meta charset="utf-8" />
    <script>
		function refreshPrice(data) {
    var p = document.getElementById('test-jsonp');
    p.innerHTML = '当前价格:' +
        data['0000001'].name +': ' + 
        data['0000001'].price + ';' +
        data['1399001'].name + ': ' +
        data['1399001'].price + ';' +
        data['1399006'].name + ': ' +
        data['1399006'].price;
}
function getPrice() {
    var
        js = document.createElement('script'),head = document.getElementsByTagName('head')[0];
    js.src = 'http://api.money.126.net/data/feed/0000001,1399006?callback=refreshPrice';
    head.appendChild(js);
}
	</script>
</head>
<body>
<div>
    <p id="test-jsonp">当前价格:</p>
    <p><button type="button" onclick="getPrice()">刷新</button></p>
</div>
</body>
</html>

通过参数callback定义回调函数名字为refreshPrice,服务端得到callback的数值为refreshPrice后,要用refreshPrice(......)把将要输出的json内容包括起来,此时,服务器生成 json 数据才能被客户端正确接收。

例2:

<html>  
<head>
<meta charset="utf-8" />  
    <title>Test Jsonp</title>  
    <script type="text/javascript">  
            function jsonpCallback(sb)  
            {  
            alert(sb['0000001'].name);  
            }  
        </script>  
    <script type="text/javascript" src="http://api.money.126.net/data/feed/0000001,1399006?callback=jsonpCallback"></script>  
</head>  
<body>  
</body>  
</html>

例3:

<html>  
<head>
<meta charset="utf-8" />  
     <title>Untitled Page</title>
      <script type="text/javascript" src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
      <script type="text/javascript">
	  
     jQuery(document).ready(function(){
        $.ajax({
             type: "get",async: false,url: "http://api.money.126.net/data/feed/0000001,1399006",dataType: "jsonp",//jsonp: "zjg",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
             //jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
             success: function(json){
                 alert(json['0000001'].name);
             },error: function(){
                 alert('fail');
             }
         });
     });
     </script>
     </head>
  <body>
  </body>
 </html>

这里需重点说明下jquery中ajax的jsonp和jsonpCallback这两个参数的含义

3 JSONP优缺点

JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。

JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

参考:

http://www.w3school.com.cn/jquery/ajax_ajax.asp

https://segmentfault.com/a/1190000006908944?utm_source=tuicool&utm_medium=referral

http://www.nowamagic.net/librarys/veda/detail/224/

http://kb.cnblogs.com/page/139725/

http://www.cnblogs.com/know/archive/2011/10/09/2204005.html

http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434499861493e7c35be5e0864769a2c06afb4754acc6000

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读