跨域請(qǐng)求

一般情況下我們的請(qǐng)求只能給自己的網(wǎng)站發(fā)送請(qǐng)求,如果給別的網(wǎng)站發(fā)送請(qǐng)求時(shí),瀏覽器會(huì)進(jìn)行同源限制,跨域請(qǐng)求就是我們的網(wǎng)站如果要獲取其他網(wǎng)站的數(shù)據(jù)的話,可以通過(guò)一下方式實(shí)現(xiàn)

例如:要獲得以下數(shù)據(jù)

def get_data(request):
    return HttpResponse('數(shù)據(jù)')

使用代碼完成跨域請(qǐng)求

request發(fā)送請(qǐng)求的時(shí)候跨域無(wú)限制

def test1(request):
    response = requests.get('http://127.0.0.1:8000/get_data/')
    return render(request, 'test1.html', {'response': response})

在前端顯示

{{ response.text }}

jsonp實(shí)現(xiàn)跨域請(qǐng)求

別人數(shù)據(jù)

def get_data(request):
    func_name = request.GET.get('callback')
    return HttpResponse('%s("數(shù)據(jù)")' % func_name)

使用jsonp實(shí)現(xiàn)跨域請(qǐng)求

<script>
    function func(arg){
        console.log(arg)
    }

    $.ajax({
        url: "http://127.0.0.1:8000/get_data/",
        type: 'GET',
        dataType: 'JSONP',
        jsonp: 'callback',
        jsonpCallback: 'list'
    });
    
</script>

注意:

首先,要讓別人對(duì)數(shù)據(jù)進(jìn)行處理

其次,為了讓獲得的數(shù)據(jù)易讀,需要將數(shù)據(jù)進(jìn)行l(wèi)ist

其原理是使用帶有src的標(biāo)簽不會(huì)收到同源限制,而且要求自己定義一個(gè)數(shù)據(jù),使用標(biāo)簽引入,而且要求別人也要在數(shù)據(jù)外面包一層數(shù)據(jù),如下

自己獲得

<script>
  function func(arg) {
    console.log(arg);
  }
</script>
<script src="http://127.0.0.1:8000/get_data/?callback=func"></script>

我們也可以手動(dòng)創(chuàng)建標(biāo)簽

<script>
    function func(arg) {
        alert(arg);

        document.head.removeChild(tag);
    }

    function jsonp(url){
        tag = document.createElement('script');
        tag.src = url;
        document.head.appendChild(tag);
    }

    jsonp('http://127.0.0.1:8000/get_data/?callback=func')
</script>

應(yīng)用場(chǎng)景:

調(diào)用者需要和數(shù)據(jù)提供者協(xié)商,首先需要數(shù)據(jù)提供者提供一個(gè)API,然后互相商討使用哪一種方式提取數(shù)據(jù),如果使用jsonp格式提取數(shù)據(jù)的話需要數(shù)據(jù)提供者對(duì)數(shù)據(jù)進(jìn)行一定的處理(獲得callback,然后使用callback包裹你的數(shù)據(jù)),如果不想讓數(shù)據(jù)提供者麻煩的話,就只能用自帶的request模塊來(lái)實(shí)現(xiàn)

core方法

首先要明白,jsonp進(jìn)行跨域請(qǐng)求的方法是繞過(guò)同源策略,使用帶有src的標(biāo)簽進(jìn)行請(qǐng)求

其次,瀏覽器為什么會(huì)進(jìn)行同源策略,其實(shí)在請(qǐng)求可以順利的到達(dá)對(duì)方的URL,也同樣能取到數(shù)據(jù),但是在返回的時(shí)候少了Access-Control-Allow-Origin 響應(yīng)頭,因此,我們的做法就是將頭加進(jìn)去

別人數(shù)據(jù)

def get_data(request):
    response = HttpResponse('數(shù)據(jù)')
    response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8899'  # 如果為*的話對(duì)所有請(qǐng)求有效
    return response

這樣讓別人的數(shù)據(jù)進(jìn)行處理之后我們自己就按照一般情況請(qǐng)求就可以了

$.ajax({
  url: 'http://127.0.0.1:8000/get_data/',
  type: 'GET',
  success: function (data) {
    console.log(data);
  }
})

如果我們給別人提供數(shù)據(jù)的話,如果允許所有的人都可以請(qǐng)求的話,使用中間件比較好

注意:

我門正規(guī)的請(qǐng)求稱為簡(jiǎn)單請(qǐng)求,但是,有時(shí)候發(fā)請(qǐng)求的時(shí)候會(huì)發(fā)送復(fù)雜請(qǐng)求,請(qǐng)求方式改變或者請(qǐng)求頭的改變可以變?yōu)閺?fù)雜請(qǐng)求,

如果發(fā)送的是復(fù)雜請(qǐng)求的話,首先會(huì)發(fā)送一個(gè)option,然后發(fā)送數(shù)據(jù),復(fù)雜請(qǐng)求接受到的request.method是option

因此數(shù)據(jù)提供者應(yīng)該在接受請(qǐng)求的時(shí)候進(jìn)行一個(gè)判斷,如果request.method的話,將請(qǐng)求方式和請(qǐng)求頭進(jìn)行修改,然后再發(fā)送數(shù)據(jù)

由于復(fù)雜請(qǐng)求發(fā)送兩次,嚴(yán)重影響效率,因此我們應(yīng)該盡量避免發(fā)送復(fù)雜請(qǐng)求

兼容復(fù)雜請(qǐng)求代碼如下

def get_data(request):
    if request.method == "OPTIONS":
        # 預(yù)檢
        response = HttpResponse()
        response['Access-Control-Allow-Origin'] = "*"
        # response['Access-Control-Allow-Methods'] = "PUT"
        response['Access-Control-Allow-Headers'] = "xxx"   # 注意在前端也是要一樣的
        return response

    elif request.method == "GET":
        response = HttpResponse("機(jī)密數(shù)據(jù)")
        response['Access-Control-Allow-Origin'] = "*"

        return response

跨站獲取相應(yīng)頭

默認(rèn)獲取到的所有響應(yīng)頭只有基本信息,如果想要獲取自定義的響應(yīng)頭,則需要再服務(wù)器端設(shè)置Access-Control-Expose-Headers。

跨站傳cookie

在跨域請(qǐng)求中,默認(rèn)情況下,HTTP Authentication信息,Cookie頭以及用戶的SSL證書無(wú)論在預(yù)檢請(qǐng)求中或是在實(shí)際請(qǐng)求都是不會(huì)被發(fā)送。

如果想要發(fā)送:

  • 瀏覽器端:XMLHttpRequest的withCredentials為true
  • 服務(wù)器端:Access-Control-Allow-Credentials為true
  • 注意:服務(wù)器端響應(yīng)的 Access-Control-Allow-Origin 不能是通配符
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言:對(duì)于跨域請(qǐng)求,很早之前就有去了解過(guò),但因?yàn)橐恢标P(guān)注的都是服務(wù)器后端開發(fā),故也就僅僅停留在概念的理解上而沒有機(jī)...
    ken_ljq閱讀 90,220評(píng)論 6 128
  • 同源策略 理解跨域首先必須要了解同源策略。同源策略是瀏覽器上為安全性考慮實(shí)施的非常重要的安全策略。何謂同源:URL...
    48892085f47c閱讀 819評(píng)論 0 6
  • 1. 所謂跨域 跨域是一種瀏覽器同源安全策略,也即瀏覽器單方面限制腳本的跨域訪問(wèn)。很多人可能誤認(rèn)為資源跨域時(shí)無(wú)法請(qǐng)...
    blurooo閱讀 6,269評(píng)論 11 54
  • 概念 當(dāng)一個(gè)資源從與該資源本身所在的服務(wù)器不同的域或端口請(qǐng)求一個(gè)資源時(shí),資源會(huì)發(fā)起一個(gè)跨域 HTTP 請(qǐng)求。出于安...
    饑人谷_Grey高閱讀 429評(píng)論 0 2
  • 太陽(yáng)升起的時(shí)候 雨還在下 我安撫跳動(dòng)了一晚的心 出門 路過(guò)江邊 有一條很大的魚 總有人躺在上面 不怕被吃掉 突然耳...
    光暗間的舞者閱讀 174評(píng)論 5 2

友情鏈接更多精彩內(nèi)容