何谓同源策略与Jsonp

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,若是缺乏了同源策略,则浏览器的正常功能可能都会受到影响。能够说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。css

同源策略,它是由Netscape提出的一个著名的安全策略。如今全部支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪一个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。若是非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。html

一、先来讲说什么是源


• 源(origin)就是指的协议、域名和端口号。
以上url中的源就是:http://www.company.com:80
若地址里面的协议、域名和端口号均相同则属于同源。
如下是相对于 http://www.a.com/test/index.html 的同源检测
• http://www.a.com/dir/page.html ----成功
• http://www.child.a.com/test/index.html ----失败,域名不一样
• https://www.a.com/test/index.html ----失败,协议不一样
• http://www.a.com:8080/test/index.html ----失败,端口号不一样python

2.什么是同源策略?


同源策略是浏览器的一个安全功能,不一样源的客户端脚本在没有明确受权的状况下,不能读写对方资源。因此a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。jquery

• 不受同源策略限制的:
一、页面中的连接,重定向以及表单提交是不会受到同源策略限制的。
二、跨域资源的引入是能够的。可是js不能读写加载的内容。如嵌入到页面中的<script src="..."></script>,<img>,<link>,<iframe>等。ajax

2、跨域  


一、什么是跨域


受前面所讲的浏览器同源策略的影响,不是同源的脚本不能操做其余源下面的对象。想要操做另外一个源下的对象是就须要跨域。django

二、跨域的实现形式


• 降域 document.domain
同源策略认为域和子域属于不一样的域,如:
child1.a.com 与 a.com,
child1.a.com 与 child2.a.com,
xxx.child1.a.com 与 child1.a.com
两两不一样源,能够经过设置 document.damain='a.com',浏览器就会认为它们都是同一个源。想要实现以上任意两个页面之间的通讯,两个页面必须都设置documen.damain='a.com'。
此方式的特色:
1. 只能在父域名与子域名之间使用,且将 xxx.child1.a.com域名设置为a.com后,不能再设置成child1.a.com。
2. 存在安全性问题,当一个站点被攻击后,另外一个站点会引发安全漏洞。
3. 这种方法只适用于 Cookie 和 iframe 窗口。
• JSONP跨域
JSONP和JSON并无什么关系!
JSONP的原理:(举例: http://127.0.0.1:8001/想获得 http://127.0.0.1:8002/中的数据)在a.com的jsonp.html里建立一个回调函数xxx,动态添加<script>元素,向服务器发送请求,请求地址后面加上查询字符串,经过callback参数指定回调函数的名字。请求地址为 http://127.0.0.1:8001?callback=xxx。在main.js中调用这个回调函数xxx,而且以JSON数据形式做为参数传递,完成回调。json

如今咱们看看 http://127.0.0.1:8001/的html代码:跨域

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<p>这是首页!</p>
<button>提交</button>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
    $("button").click(function () {
        alert(123)
        $.ajax({
            url: "http://127.0.0.1:8002//test/",
            success: function (data) {
                console.log(data)
            }
        })
    })
</script>
</body>
</html>

在这个代码里面调用了8002的资源。浏览器

8802:的views代码:安全

from django.shortcuts import render, HttpResponse

# Create your views here.


def test(request):
    print("会出现吗。非常期待哦")

    return HttpResponse("this is test")

这是一个简单的调用。你会发现。浏览器不容许你进行调用。

由于控制台已经给你调用了

说明是浏览器不容许你进行跨域.

可是大家发现没有。一样是跨域调用。我进行jquery的cdn调用就不会进行拦截。

看到这里你的内心难道就没有点想法吗?

没有,既然不给我进行js的跨域,那我跨域假装成上面的那种方式进行调用呀!说干就干,撸起手就是干。

8001的HTML代码如图:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<p>这是首页!</p>
{#{% csrf_token %}#}
<button>提交</button>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
$("button").click(function () {

        var html_script = $("<script>");
        html_script.attr("src","http://127.0.0.1:8002/test/");
        html_script.attr("id","test");
        $("body").append(html_script);
        $("#test").remove();//生成的标签调用完毕,立刻移除掉。
})
    function get_data(test2_data) {
        console.log(test2_data)
    }
</script>
</body>
</html>

8002 的views代码:

from django.shortcuts import render, HttpResponse

# Create your views here.


def test(request):
    print("会出现吗。非常期待哦")
    return HttpResponse("get_data('ok')")  # 传递一个跟8001同名的get_data()函数

这样调用跨域的资源就不会出错了。

。如今为了更加灵活,如今将在客户端定义的回调函数传送给服务端。服务端就会返回逸直接定义的回调函数名的方法。将获取的json数据传入这个方法就能够完成回调了。

8001代码也就是客户端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<p>这是首页!</p>
{#{% csrf_token %}#}
<button>提交</button>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
$("button").click(function () {

        var html_script = $("<script>");
        html_script.attr("src","http://127.0.0.1:8002/test/?callbacks=get_data");
        html_script.attr("id","test");
        $("body").append(html_script);
        $("#test").remove();//生成的标签调用完毕,立刻移除掉。
})
    function get_data(test2_data) {
        console.log(test2_data)
    }
</script>
</body>
</html>

8002也就是服务端只需这样调用便可:

from django.shortcuts import render, HttpResponse
import json

# Create your views here.


def test(request):
    print("会出现吗。非常期待哦")
    func = request.GET.get("callbacks")
    print(func)
    a_dict = {"key": "values"}
    return HttpResponse("%s(%s)" % (func, json.dumps(a_dict)))  # 须要把数据进行序列化方能够传递过去

让咱们来看看结果呗

这就跨域调用数据成功了。

jQuery中的Jsonp方法

只须要改动8001中的html代码便可:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<p>这是首页!</p>
{#{% csrf_token %}#}
<button>提交</button>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
$("button").click(function () {
    f("http://127.0.0.1:8002/test/")
})
 function f(url) {
     $.ajax({
         url: url,
         dataType:"jsonp",
         jsonp: 'callbacks', //这里的值(callbacks)至关于url中的建的名字
         jsonpCallback: 'ok', // 这里的值(ok)至关于回调函数的函数名,也就是url中的值
         success:function (data) {
             console.log(data)
         }
     });
 }
</script>
</body>
</html>

你能够正常的跨域调用。

可是上面的代码有个能够不用有:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<p>这是首页!</p>
{#{% csrf_token %}#}
<button>提交</button>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
$("button").click(function () {
    f("http://127.0.0.1:8002/test/")
})
 function f(url) {
     $.ajax({
         url: url,
         dataType:"jsonp",
         jsonp: 'callbacks', //这里的值(callbacks)至关于url中的建的名字
         //jsonpCallback: 'ok', // 这里的值(ok)至关于回调函数的函数名,也就是url中的值
         success:function (data) {
             console.log(data)
         }
     });
 }
</script>
</body>
</html>

从这里能够看出不必定须要本身定义回调函数名也能够,jsonp也能够帮你生成函数名:

经过CORS实现跨域调用。

相关文章
相关标签/搜索