瀏覽器的跨域解決方案


一. jsonp解決跨域問題

  1. 函數中傳參

    dom1中的HTML

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>xyz</title>
</head>
<body>
<button id="b1">點我</button>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
  function rion(res) {
    console.log(res);
  }
</script>
<script src="http://127.0.0.1:8002/abc/"></script>
</body>
</html>

  demo2 中的視圖函數:

def abc(request):
    res = {"code": 0, "data": ["SNIS-561", "SNIS-517", "SNIS-539"]}
    return HttpResponse("rion({})".format(json.dumps(res)))

  JQuery中getJSON方法:

    demo2中HTML

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>xyz</title>
</head>
<body>
<button id="b1">點我</button>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
  $("#b1").click(function () {
    $.getJSON("http://127.0.0.1:8002/abc/?callback=?", function (res) {
      console.log(res);
    })
  });
</script>
</body>
</html>

  

  要注意的是在url的后面必須要有一個callback參數,這樣getJSON方法才會知道是用JSONP方式去訪問服務,callback后面的那個?是jQuery內部自動生成的一個回調函數名。

 

 

二. CORS解決跨域問題

  CORS是一個W3C標准,全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源服務器發出XMLHttpRequest請求,從而解決AJAX只能同源使用的限制.

  瀏覽器將CORS請求分為兩類: 簡單請求非簡單請求

  一個請求需要同時滿足 以下兩大條件 才屬於簡單請求.

(1) 請求方法是以下三種方法之一:
    HEAD
    GET
    POST

(2)HTTP的頭信息不超出以下幾種字段:
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain

簡單請求的處理方式

 在跨域場景下,當瀏覽器發送簡單請求時,瀏覽器會自動在請求頭中添加表明請求來源的 Origin 字段。

  

  我們的后端程序只需要在返回的響應頭中加上 Access-Control-Allow-Origin 字段,並且把該字段的值設置為 跨域請求的來源地址或簡單的設置為 * 就可以了。

例如:我們可以在Django中間件中的process_response方法來給相應對象添加該字段。

from django.utils.deprecation import MiddlewareMixin


class CorsMiddleware(MiddlewareMixin):

    def process_response(self, request, response):
        # 給響應頭加上 Access-Control-Allow-Origin 字段 並簡單的設置為 *
        response['Access-Control-Allow-Origin'] = '*'
        return response

 

非簡單請求的處理方式 >>  

  我們開發中常用到的那些請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json的都是非簡單請求。

 

  對於非簡單請求,瀏覽器通常都會在請求之前發送一次 OPTIONS 預檢 請求。該請求會像后端服務詢問是否允許從當前源發送請求並且詢問允許的 請求方法 和 請求頭字段

  

解決方案在上面Django的中間件中添加如下代碼:

from django.utils.deprecation import MiddlewareMixin


class CorsMiddleware(MiddlewareMixin):

    def process_response(self, request, response):
        # 給響應頭加上 Access-Control-Allow-Origin 字段 並簡單的設置為 *
        response['Access-Control-Allow-Origin'] = '*'
        if request.method == 'OPTIONS':
            # 允許發送 PUT 請求
            response['Access-Control-Allow-Methods'] = 'PUT, DELETE'
            # 允許在請求頭中攜帶 Content-type字段,從而支持發送json數據
            response['Access-Control-Allow-Headers'] = 'Content-type'
        return response

 

 

三. 使用 Django-corset-headers 解決跨域問題

  

我們這個中間件確實能解決目前的CORS跨域問題,但是我們的土方法肯定是不夠嚴謹的,已經有人造好輪子-- django-cors-headers 了。

 

我們只需要安裝這個包,然后按需要配置一下就可以了。

 

安裝

 

pip install django-cors-headers

 

注冊APP

 

INSTALLED_APPS = [
    ...
    'app01.apps.App01Config',
    'corsheaders',  # 將 corsheaders 這個APP注冊
]

 

添加中間件

 

必須放在最前面,因為要先解決跨域的問題。只有允許跨域請求,后續的中間件才會正常執行。

 

復制代碼
MIDDLEWARE = [
    'corsheaders.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',
]
復制代碼

 

配置

 

你可以選擇不限制跨域訪問

 

CORS_ORIGIN_ALLOW_ALL = True

 

或者你可以選擇設置允許訪問的白名單

 

CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
    # '<YOUR_DOMAIN>[:PORT]',
    '127.0.0.1:8080'
)

 

更多詳細配置詳細請查看django-cors-headers項目

 


免責聲明!

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



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