首頁 > 後端開發 > Python教學 > 將 CSRF 保護與 Django 和 AJAX 請求結合使用

將 CSRF 保護與 Django 和 AJAX 請求結合使用

DDD
發布: 2025-01-07 18:15:39
原創
339 人瀏覽過

Using CSRF Protection with Django and AJAX Requests

透過 CSRF 保護保護 Django AJAX 請求

Django 的內建 CSRF(跨站請求偽造)保護在使用 django-admin startproject 建立專案時預設啟用,利用 CSRF 令牌來防範惡意請求。 此中間件已新增至您的 settings.py.

對 Django 應用程式的每個 POST 請求都需要有效的 CSRF 令牌。在 Django 範本中,這是透過使用 POST 方法在任何表單中包含 {% csrf_token %} 來實現的。 然而,使用單獨的前端 AJAX 請求處理 CSRF 保護需要不同的方法。

本教學示範使用來自單獨前端的 AJAX 請求來保護簡單的 Django 應用程式。

應用程式設定

我們的範例應用程式有兩個端點:

  • GET /get-picture:擷取儲存在伺服器上的映像的 URL。
  • POST /set-picture:更新儲存在伺服器上的映像的 URL。

為了簡單起見,省略了錯誤處理。 初始後端程式碼(在urls.py中)如下:

<code class="language-python">from django.urls import path
from django.http import JsonResponse
import json

picture_url = "https://picsum.photos/id/247/720/405"

def get_picture(request):
    return JsonResponse({"picture_url": picture_url})

def set_picture(request):
    if request.method == "POST":
        global picture_url
        picture_url = json.loads(request.body)["picture_url"]
        return JsonResponse({"picture_url": picture_url})

urlpatterns = [
    path("get-picture", get_picture),
    path("set-picture", set_picture)
]</code>
登入後複製

對應的前端功能(簡體):

<code class="language-javascript">// GET request to retrieve the image URL
async function get_picture() {
    const res = await fetch("http://localhost:8000/get-picture");
    const data = await res.json();
    return data.picture_url;
}

// POST request to update the image URL
async function set_picture(picture_url) {
    const res = await fetch("http://localhost:8000/set-picture", {
        method: "POST",
        body: JSON.stringify({ "picture_url": picture_url })
    });
}</code>
登入後複製

為了處理跨來源資源共享(CORS),我們將使用 django-cors-headers 套件。

啟用 CORS 和 CSRF 保護

安裝django-cors-headers

<code class="language-bash">pip install django-cors-headers</code>
登入後複製

配置settings.py

<code class="language-python">INSTALLED_APPS = [
    "corsheaders",
    # ... other apps
]

MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware",
    # ... other middleware
]

CORS_ALLOWED_ORIGINS = ["http://localhost:4040"] # Adjust port as needed
CSRF_TRUSTED_ORIGINS = ["http://localhost:4040"] # Add your frontend origin</code>
登入後複製

雖然 GET 請求現在可以正常工作,但 POST 請求將由於 CSRF 保護而失敗。 為了解決這個問題,我們需要手動管理 CSRF 令牌。

取得並使用 CSRF 令牌

建立一個新視圖來提供 CSRF 令牌:

<code class="language-python">from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import JsonResponse

@ensure_csrf_cookie
def get_csrf_token(request):
    return JsonResponse({"success": True})

urlpatterns = [
    # ... other paths
    path("get-csrf-token", get_csrf_token),
]</code>
登入後複製

更新前端以取得令牌(使用js-cookie):

<code class="language-javascript">fetch("http://localhost:8000/get-csrf-token", { credentials: "include" });</code>
登入後複製

credentials: "include" 選項可確保瀏覽器處理任何 Set-Cookie 標頭,儲存 csrftoken cookie。 檢查瀏覽器開發者工具中的網路標籤以驗證 cookie 是否已設定。

修改 POST 請求

最後,修改 set_picture 函數以在標頭中包含 CSRF 令牌:

<code class="language-javascript">async function set_picture(picture_url) {
    const res = await fetch("http://localhost:8000/set-picture", {
        method: "POST",
        credentials: "include",
        headers: {
            'X-CSRFToken': Cookies.get("csrftoken")
        },
        body: JSON.stringify({ "picture_url": picture_url })
    });
}</code>
登入後複製

這會新增 X-CSRFToken 標頭以及 csrftoken cookie 中的值,從而啟用成功的 POST 請求。

重要注意事項

這種方法有局限性,尤其是在不同域上部署前端和後端時。 瀏覽器安全性原則可能會阻止設定或存取第三方 cookie,進而影響 CSRF 令牌管理。

資源

以上是將 CSRF 保護與 Django 和 AJAX 請求結合使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板