何謂同源策略與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實現跨域調用。

相關文章
相關標籤/搜索