同源策略和解決

同源策略

同源策略(Same origin policy)是一種約定,它是瀏覽器最核心也最基本的安全功能,若是缺乏了同源策略,則瀏覽器的正常功能可能都會受到影響。能夠說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。html

同源策略,它是由Netscape提出的一個著名的安全策略。如今全部支持JavaScript 的瀏覽器都會使用這個策略。所謂 同源是指,域名,協議,端口相同。當一個瀏覽器的兩個tab頁中分別打開來 百度和谷歌的頁面當瀏覽器的百度tab頁
執行一個腳本的時候會檢查這個腳本是屬於哪一個頁面的,即檢查是否同源,只有和百度同源的腳本纔會被執行。那麼在請求數據時,瀏覽器會在控制檯中報一個異常,提示拒絕訪問。

 例子

項目一 index.html 端口 8000
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>同源2</title>
</head>
<body>
<h3>主頁</h3>

<button class="get_service">點我</button>

<script src="/static/jquery-3.3.1.js"></script>
<script>

        $(".get_service").click(function () {
            $.ajax({
                url:"http://127.0.0.1:8008/service/",  // 注意 我請求的是另外一個服務器
                success:function (data) {
                    console.log(data);
                }

            })
        });
</script>

項目二  view.py  端口 8008前端

from django.shortcuts import render,HttpResponse

# Create your views here.

def index(request):

    return render(request,'index.html')

import json
def service(request):
    info = {"name": "yk", "age": 20}

    return HttpResponse(json.dumps(info))

當我點擊項目一 裏的 button 按鈕時,提示以下錯誤jquery

已攔截跨源請求:同源策略禁止讀取位於 http://127.0.0.1:8008/service/ 的遠程資源。(緣由:CORS 頭缺乏 'Access-Control-Allow-Origin')。

ajax

Jsonp

JSONP(JSON with Padding)是JSON的一種「使用模式」,可用於解決主流瀏覽器的跨域數據訪問的問題。其核心思想是利用JS標籤裏面的跨域特性進行跨域數據訪問,django

在JS標籤裏面存在的是一個跨域的URL,實際執行的時候經過這個URL得到一段字符串,這段返回的字符串必須是一個合法的JS調用,經過EVAL這個字符串來完成對得到的數據的處理。json

jsonp是json用來跨域的一個東西。原理是經過script標籤的跨域特性來繞過同源策略跨域

 

項目一 index.html 端口 8000瀏覽器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>同源2</title>
</head>
<body>
<h3>主頁</h3>
<button class="get_service">點我</button> <script src="/static/jquery-3.3.1.js"></script> <script> function func(arg) { console.log(arg); console.log(typeof arg); data = JSON.parse(arg); console.log(data); console.log(typeof data); } </script> <script src="http://127.0.0.1:8008/service/"></script>

項目二  view.py  端口 8008安全

from django.shortcuts import render,HttpResponse

# Create your views here.

def index(request):

    return render(request,'index.html')

import json
def service(request):
    info = {"name": "yk", "age": 20}

    return HttpResponse("func('%s')" % json.dumps(info))

當再次刷新index.htnl服務器

能夠見到,成功訪問到數據

 

項目一 index.html 端口 8000  點擊按鈕獲取數據

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>同源2</title>
</head>
<body>
<h3>主頁</h3>

<button class="get_service">點我</button>

<script src="/static/jquery-3.3.1.js"></script>
<script>
    function func(arg) {

        console.log(arg);
        console.log(typeof arg);

        data = JSON.parse(arg);
        console.log(data);
        console.log(typeof data);
    }

</script>

    $(".get_service").click(function () {#}

    $(".get_service").click(function () {

        var ele_script = $("<script>");

        ele_script.attr("src", "http://127.0.0.1:8008/service/");
        ele_script.attr("id", "jsonp");
        $("body").append(ele_script);

        $("#jsonp").remove();}
    )

</script>

jQuery對JSONP的實現

項目一 index.html 端口 8000

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>同源2</title>
</head>
<body>
<h3>主頁</h3>

<button class="get_service">點我</button>

<script src="/static/jquery-3.3.1.js"></script>
<script>

    $(".get_service").click(function () {

        $.ajax({
            url: "http://127.0.0.1:8008/service/",
            type: "get",
            dataType: "jsonp",   //必須有,告訴server,此次訪問要的是一個jsonp的結果。
            jsonp: "callbacks",  //jQuery幫助隨機生成的:callbacks="jqueryxxxx"
       // jsonpCallback:"SayHi" ,  // 若是指定 ,則回調函數名 爲SayHi
            success: function (data) {
                console.log(data)
            }
        })

    })

</script>

</body>
</html>

項目二  view.py  端口 8008

from django.shortcuts import render,HttpResponse

# Create your views here.

def index(request):

    return render(request,'index.html')

import json

def service(request):
    func = request.GET.get("callbacks")   # 獲取 回調函數名

    info = {"name": "yk", "age": 20}

    return HttpResponse("%s('%s')" % (func,json.dumps(info)))

  jsonp: 'callbacks'就是定義一個存放回調函數的鍵,jsonpCallback是前端定義好的回調函數方法名'SayHi',server端接受callback鍵對應值後就能夠在其中填充數據打包返回了; 

  jsonpCallback參數能夠不定義,jquery會自動定義一個隨機名發過去,那前端就得用回調函數來處理對應數據了。利用jQuery能夠很方便的實現JSONP來進行跨域訪問。  

注意 JSONP必定是GET請求

 

CORS

 

CORS須要瀏覽器和服務器同時支持。目前,全部瀏覽器都支持該功能,IE瀏覽器不能低於IE10。

 

整個CORS通訊過程,都是瀏覽器自動完成,不須要用戶參與。對於開發者來講,CORS通訊與同源的AJAX通訊沒有差異,

代碼徹底同樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。

 

所以,實現CORS通訊的關鍵是服務器。只要服務器實現了CORS接口,就能夠跨源通訊。

支持跨域,簡單請求

服務器設置響應頭:Access-Control-Allow-Origin = '域名' 或 '*'

支持跨域,複雜請求

因爲複雜請求時,首先會發送「預檢」請求,若是「預檢」成功,則發送真實數據。

  • 「預檢」請求時,容許請求方式則需服務器設置響應頭:Access-Control-Request-Method
  • 「預檢」請求時,容許請求頭則需服務器設置響應頭:Access-Control-Request-Headers
 
 

 

def service(request):

    info={"name":"egon","age":34,"price":200}

    response=HttpResponse(json.dumps(info))
    response["Access-Control-Allow-Origin"]="http://127.0.0.1:8008"  # 設置響應頭:Access-Control-Allow-Origin = '域名' 或 '*'
    #response["Access-Control-Allow-Origin"]="*"
    return  response
相關文章
相關標籤/搜索