首页 > 编程笔记 > JavaScript笔记 > JS DOM

JSONP跨域请求入门教程(附带实例)

JSONP (JSON with Padding)是在客户端生成 <script> 标签来调用跨域脚本(服务器端脚本文件)的一个非官方协议。JSONP 允许在服务器端动态生成 JavaScript 字符串返回给客户端,通过 JavaScript 回调函数的形式实现跨域调用。

示例1

现在很多 JavaScript 技术框架都使用 JSONP 实现跨域异步通信,如 dojo、jQuery、Youtobe、GData API、Google Social Graph API、Digg API 等。 示例1 下面示例演示了如何使用 script 实现异步 JSON 通信。

1) 在服务器端的 JavaScript 文件中输入下面代码(server.js).
callback({
    "title" : "JSONP Test",
    "link" : "http://www.mysite.cn/",
    "modified" : "2016-12-1",
    "items" : [{
        "title" : "百度",
        "link" : "http://www.baidu.com/",
    "description" : "百度侧重于中国网民的搜索习惯,搜索结果更加大众化。"
    },{
    "title" : "谷歌",
    "link" : "http://www.google.cn/",
    "description" : "谷歌搜索结果更客观,尤其在搜索技术性文章的时候,结果更加精准。"
    }]
})
callback 是回调函数的名称,使用小括号运算符调用该函数,并传递一个 JavaScript 对象。在这个对象中包含 4 个属性:title、link、modified、items。其中前 3 个属性值是字符串,第 4 个属性 items 包含一个数组,数组中包含两个对象。这两个对象又包含两个属性:title、link。

通过这种方式可以在一个 JavaScript 对象中包含更多信息,在客户端的 <script> 标签中可以利用 src 属性把服务器端的这些 JavaScript 脚本作为响应信息引入到客户端的 <script> 标签中。

2) 在回调函数中逐层遍历和分解 JSON 数据,有序显示所有响应信息(test.html)。
function callback(info){
    var temp = "";
    for(var i in info){
        if(typeof info[i] != "object"){
            temp += i + " = \"" + info[i] + "\"<br />";
     }else if( (typeof info[i] == "object") && (info[i].constructor == Array)){
        temp += "<br />" + i + " = " + "<br /><br />";
        var a = info[i];
        for(var j = 0; j < a.length; j ++ ){
            var o = a[j];
           for(var e in o){
               temp += "&nbsp;&nbsp;&nbsp;&nbsp;" + e + " = \"" + o[e] + "\"<br />";
            }
             temp +=  "<br />";
            }
        }
    }
    var div  = document.getElementById("test");
    div.innerHTML = temp;
}

3) 完成用户提交信息的操作。客户端提交页面(test.html)的代码如下:
function request(url){
    if( ! document.script){
        document.script = document.createElement("script");
        document.script.setAttribute("type", "text/javascript");
        document.script.setAttribute("src", url);
        document.body.appendChild(document.script);
    } else {
        document.script.setAttribute("src", url);
    }
}
window.onload = function(){
    var b = document.getElementsByTagName("input")[0];
    b.onclick = function(){
        var url = "server.js"
        request(url);
    }
}
<h1>客户端信息提交页面</h1>
<input name="submit" type="button" id="submit" value="向服务器发出请求" />
<div id="test"></div>
回调函数和请求函数的名称并不是固定的,用户可以自定义这些函数的名称。

4) 保存页面,在浏览器中预览,演示效果如下图所示。


 

示例2

下面结合一个示例说明如何使用 JSONP 实现跨域异步信息交互。

1) 在客户端调用 JSONP 约定的 URL 服务,获取 JSONP 格式数据。

所谓 JSONP 约定的 URL 服务,就是在请求的 URL 中必须附加在客户端可以回调的函数,并按约定正确设置回调函数参数,默认参数名为 jsonp 或 callback。

根据约定,只要服务器能够识别即可。本例定义 URL 服务的代码如下:
http://localhost/mysite/server.php?jsonp=callback&d=1
其中参数 jsonp 的值为约定的回调函数名。

JSONP 格式的数据就是把 JSON 数据作为参数传递给回调函数。如果响应的 JSON 数据如下。
{
    "title" : "JSONP Test",
    "link" : "http://www.mysite.cn/",
    "modified" : "2019-10-11",
    "items" : {
        "id" : 1,
        "title" : "百度",
        "link" : "http://www.baidu.com/"
    }
}
那么真正返回到客户端的脚本标记如下:
callback ({
    "title" : "JSONP Test",
    "link" : "http://www.mysite.cn/",
    "modified" : "2019-10-11",
    "items" : {
        "id" : 1,
        "title" : "百度",
        "link" : "http://www.baidu.com/"
    }
})

2) 当客户端向服务器端发出请求后,服务器应该完成两件事情:一是接收并处理参数信息,如获取回调函数名;二是要根据参数信息生成符合客户端需要的脚本字符串,并把这些字符串响应给客户端。例如,服务器端的处理脚本文件如下(server.php)。
<?php>
    header ("Content-Type: text/html; charset=utf-8");
    $callback = $_GET["jsonp"];
    $id = $_GET["id"];
    echo $callback."(";
?>
{
    "title" : "JSONP Test",
    "link" : "http://www.mysite.cn/",
    "modified" : "2019-10-11",
    "items" : 
<?php
    if ($id == "1"){
?>
    {
         "title" : "百度",
        "link" : "http"//www.baidu.com/"
    }
<?php
} else if ($id == "2") {
?>
    {
         "title" : "谷歌",
        "link" : "http"//www.google.cn/"
    }
<?php
} else {
    echo "";
}
echo "})";
?>

3) 在客户端设计回调函数,利用回调函数把 JSON 数据显示出来。
function callback (info) {
    var temp = "";
    for (var i in info) {
        if (typeof info[i] != "object") {
            temp += i + "=\"" + "\"<br />";
        } else if ((typeof info[i] == "object")) {
            temp += "<br />" + i + "=" + "{<br />";
            var o = info[i];
            for (var j in o) {
                temp += "&nbsp;&nbsp;&nbsp;&nbsp;" + j + "=\"" + o[j] + "\"<br />";
            }
            temp += "}";
        }
    }
    var div = document.getElementById("test");
    div.innerHTML = temp;
}

4) 设计客户端提交页面与信息展示。在页面中插入一个 <div> 标签,然后把输出的信息插入到该标签内。同时设计一个交换按钮,单击该按钮将触发请求函数,并向服务器端发去请求。响应完毕,在客户端调用回调函数,对响应的数据进行处理和显示。
<div id="test"></div>

恶意攻击者可以通过发送畸形 JSON 数据实现攻击目的,这样 eval() 函数就会执行这些恶意代码。为了安全,应该采取一些方法来保护 JSON 数据的安全使用。例如,使用正则表达式过滤掉 JSON 中不安全的 JavaScript 字符串。
var my_JSON_object = ! (/[^,:{}\[\]0-9.\-+Eaeflnr-u\n\r\t]/.test(text.replace(/"(\\.|[^"\\])*"/g,''))) && eval('(' + test + ')');
这个正则表达式能够检查 JSON 字符串,如果没有发现字符串中包含的恶意代码,则再使用 eval() 函数把它转换为 JavaScript 对象。

所有教程

优秀文章