如何使用CORS解決跨域問題


一,為什么會有跨域問題

  跨域問題的出現,是因為瀏覽器的同源策略對ajax請求進行阻攔了,但是並不是所有的請求都給做當做跨域,;像是一般的href屬性,a標簽什么的都不進行攔截

 

二,什么是同源策略

  同源策略是一種約定,它是瀏覽器最核心也會是最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。

  它約定請求的url地址,必須與瀏覽器的url地址處於同域上,也就是域名,端口,協議都相同。

  如果不同,就會報錯:

已攔截跨源請求:同源策略禁止讀取位於 http://127.0.0.1:8001/SendAjax/ 的遠程資源。(原因:CORS 頭缺少 'Access-Control-Allow-Origin')。

  實際上的結果是,請求以及被發送過去了,目標服務器也對做出了響應,只是瀏覽器對非同源請求的放回結果做了攔截。

三,CORS簡介

  CORS,跨域資源共享,它需要瀏覽器和服務器同事支持,目前,所有瀏覽器都支持該功能,IE瀏覽器不能低於IE10。

  整個CORS通信中,都是瀏覽器自動完成的,不需要用戶的參與,對於開發者來說cors通信與同源的ajax沒有差別,代碼完全一樣。瀏覽器一旦發現ajax請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有察覺。

  要實現cors通信,主要是在服務器,也就是獲得數據的一方做處理。

四,cors基本的流程

  1,瀏覽器將請求分為兩類,一類是簡單請求,一類是非簡單請求,滿足下列條件的就是簡單請求,否則即使非簡單請求:

條件:
    1、請求方式:HEAD、GET、POST
    2、請求頭信息:
        Accept
        Accept-Language
        Content-Language
        Last-Event-ID
        Content-Type 對應的值是以下三個中的任意一個
                                application/x-www-form-urlencoded
                                multipart/form-data
                                text/plain
 
注意:同時滿足以上兩個條件時,則是簡單請求,否則為復雜請求

  2,簡單請求和復雜請求的區別:

    簡單請求:一次請求

    非簡單請求:兩次請求,在發送數據之前會先發第一次請求做預檢,只有預檢通過后在發一次請求作為數據傳輸。

  3,關於預檢:

- 請求方式:OPTIONS
- “預檢”其實做檢查,檢查如果通過則允許傳輸數據,檢查不通過則不再發送真正想要發送的消息
- 如何“預檢”
     => 如果復雜請求是PUT等請求,則服務端需要設置允許某請求,否則“預檢”不通過
        Access-Control-Request-Method
     => 如果復雜請求設置了請求頭,則服務端需要設置允許某請求頭,否則“預檢”不通過
        Access-Control-Request-Headers

  4,CORS優缺點

    CORS的優點:可以發任意請求

    CORS的缺點:上是復雜請求的時候得先做一個預檢,再發真實的請求,發了兩次請求會有性能上的損耗。

五,實現CORS請求

  局部使用:

    簡單請求(get)客戶端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<button id="a" class="btn btn-success">go</button>
<script>
    $("#a").click(function () {
        $.ajax({
            url:'http://127.0.0.1:8000/time/',
            type:'get',
            success:function (data) {
                alert(data)
            }
            }
        )
    })
</script>
</body>
</html>

    簡單請求服務端:

def get_time(request):
    if request.method == 'GET':
        ntime = time.strftime('%Y-%m-%d %X')
        obj = HttpResponse(ntime)
        obj['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8001'
        return obj

    復雜請求(post+contentType)客戶端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<button id="a" class="btn btn-success">go</button>
<script>
    $("#a").click(function () {
        $.ajax({
            url:'http://127.0.0.1:8000/money/',
            type:'post',
            contentType:'application/json',
            data:{"name":"yjh"},
            success:function (data) {
                alert(data)
            }
            }
        )
    })
</script>
</body>
</html>

    復雜請求服務端:

from django.http import QueryDict
def get_money(request):
    # print(request.body)
    if not request.body:
        obj = HttpResponse('1000000000000')
    else:
        data = request.body # post請求傳過來的數據以二進制的形式存放於request.body
        # 將request.body的二進制數據轉化為字典形式
        dic = QueryDict(data.decode('utf-8'),encoding='utf-8')
        name = dic.get('name')
        obj = HttpResponse(name)
    if request.method == 'OPTIONS':
        obj['Access-Control-Allow-Headers'] = 'Content-Type'
    obj['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8001'
    return obj

六:全局配置

  由於是全局配置,所以應該寫在中間件中。然而,我們知道瀏覽器是在返回的時候出現的禁用,因此我們我們需要重寫process_response方法。

  第一步:在應用文件夾根目錄中,新建一個my_middleware.py文件

  第二步:在該py文件夾中寫上:

from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
    def process_response(self,request,response):
        if request.method=="OPTIONS":
            #可以加*
            response["Access-Control-Allow-Headers"]="Content-Type"
        response["Access-Control-Allow-Origin"] = "http://localhost:8080"
        return response

  第三步:在settings.py中配置:

MIDDLEWARE = [
    'app01.my_middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM