跨域一

什么是跨域?

URL                          说明                     是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js        同一域名下                 允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js     同一域名下不同文件夹         允许
http://www.a.com:8000/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://70.32.92.74/b.js          域名和域名对应ip             不允许
http://www.a.com/a.js
http://script.a.com/b.js         主域相同,子域不同           不允许
http://www.a.com/a.js
http://a.com/b.js               同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js
http://www.a.com/b.js           不同域名                     不允许

JSONP

原理:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。

缺点:只能实现get 请求,不能实现post 请求。

demo:

应为它用到的只是所有 HTML 元素中一个简单的 script 元素。看到这是不是觉得越发奇怪了?没关系,继续看下去就会茅厕(塞)顿开的,嘿嘿~来看个例子吧:
demo.html:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Demo</title>
</head>
<body>
<script type="text/javascript">
    function say(words) {
       alert(words);
    }
</script>
<script type="text/javascript" src="demo.js"></script>
</body>
</html>

demo.js:

say("Hello, everyone!");

运行 demo.html 文件后,是不是看到写着“Hello, everyone!”的警告框了?你可能会觉得这个例子很简单,没什么了不起的,甚至会在想:这和 JSONP 有关系吗?那么,我可以很肯定的告诉你:有关系!而且,这个例子实际上就是 JSONP 的原型!你也许会想到,JSONP 不是访问远程数据的吗?对,试想一下,如果 demo.js 文件在其它域的服务器上呢?结果会不会出现问题?我也可以很负责的告诉你:不会!你可以将上面例子中的 demo.js 更改为:http://demo.hpyer.cn/php/jsonp.php?callback=say 再试一下。
现在,聪明的你应该已经明白 JSONP 到底是怎么回事了,那么,再来解释一下本节开头第一句话吧。看过 demo.js 文件的内容,应该知道,其只是对一个函数(通常称之为:回调函数)的调用,而需要交互的数据则通过参数形势进行返回。所以通过 JSONP 访问的服务器需要提供一个可以设置回调函数名的接口,就像 http://demo.hpyer.cn/php/jsonp.php?callback=say 中的 callback,所以,综上所述 JSONP 是需要服务器端的支持的。附上 jsonp.php 的源码:

 
<?php
$type = isset($_GET['type']) ? $_GET['type'] : '';
$callback = isset($_GET['callback']) ? $_GET['callback'] : '';
$json = '';
if ($type == 'json') {
   $json = '{
   "Image": {
   "Width": 800,
   "Height": 600,
   "Title": "View from 15th Floor",
   "Thumbnail": {
   "Url": "http://www.example.com/image/481989943",
   "Height": 125,
   "Width": "100"
   },
   "IDs": [116, 943, 234, 38793]
   }
   }';
} else {
   $json = '"Hello, everyone!"';
}
if (!empty($callback)) {
   $json = $callback . '(' . $json . ')';
}
echo $json;

jquery 中的应用:
自 1.2 版本起,jQuery 加入了对 JSONP 的支持。我们可以很容易的利用 $.getJSON() 方法(或者其它基于 $.ajax() 的方法),来跨域加载 JSON 数据。来个例子吧:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Demo</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
function do_jsonp() {
   $.getJSON("http://demo.hpyer.cn/php/jsonp.php?type=json&callback=?",
   function(data) {
   $('#result').val('data.Image.IDs: ' + data.Image.IDs);
   });
}
</script>
</head>
<body>
<a href="javascript:do_jsonp();">Click me</a><br />
<textarea id="result" cols="50" rows="5"></textarea>
</body>
</html>

你可能注意到上面的例子中,url 被写成了 http://demo.hpyer.cn/php/jsonp.php?type=json&callback=?,需要说明的是,这个问号会被 jQuery 自动替换为回调函数的函数名(如果是一个匿名函数,jQuery 会自动生成一个带时间戳的函数名)。

 看我在项目中的一个例子:
//定义Ajax函数
function ajaxFun() {
    var timeStamp = Math.floor(new Date().getTime() / 1000);
    var url = "http://apiso.alidemo.3gpp.cn/httpserver/cp/yisou/ali_feedback_interface.php?callback=jsonpCallback&feedbacktype=add&type=" + feedbackNumber + "&book=" + me.mixedInfo.title + "&author=" + me.mixedInfo.author + "&chapter=" + me.mixedInfo.cname + "&chapterid=" + me.mixedInfo.cid + "&questiondesc=" + text + "&platform=1&t=" + timeStamp + "&sn=" + md5("d30fcd1a9f1900fa049b4766e0a275e1" + timeStamp);
    var scriptObj = document.createElement("script");
    scriptObj.src = url;
    scriptObj.id = "jsonpScript";
    document.body.appendChild(scriptObj);
    //jsonp回调函数,jsonpCallback必须为全局函数,因为jsonp返回的是在全局环境中执行函数的语句,即jsonpCallback(data)
    window.jsonpCallback = function(data) {
        switch (data.code) {
            case "1":
                novel.readerPrompt('提交成功,即将返回……', 1, function() {
                    window.history.go(-1);
                });
                break;
            case "0":
                novel.readerPrompt('提交失败。', 2);
                break;
            case "900":
                novel.readerPrompt('提交失败,验证失败。', 2);
                break;
        }
        //成功后删除scriptObj,后面的setTimeout就不会执行了
        if (document.getElementById("jsonpScript")) {
            document.body.removeChild(scriptObj);
        }
    }
    //设置超时,超时的话直接显示提交成功
    setTimeout(function() {
        if (document.getElementById("jsonpScript")) {
            document.body.removeChild(scriptObj);
            novel.readerPrompt('提交成功,即将返回……', 1, function() {
                window.history.go(-1);
            });
        }
    }, 2000);
}
ajaxFun();

 参考:

web开发之跨域访问篇(二)

关于javascript跨域及JSONP的原理与应用

原文地址:https://www.cnblogs.com/eaysun/p/4661286.html