★ 背景說明 在Django REST framework (DRF) 前後端分離項目中,解決CSRF問題通常有以下幾種方法: 1. 禁用CSRF驗證,但這會降低安全性。(不推薦) 2. 使用csrftoken cookie 3. 在前端每次 POST、PUT 或 DELETE 請求前先發起一個GE ...
★ 背景說明
在Django REST framework (DRF) 前後端分離項目中,解決CSRF問題通常有以下幾種方法:
1. 禁用CSRF驗證,但這會降低安全性。(不推薦)
2. 使用csrftoken cookie
3. 在前端每次 POST、PUT 或 DELETE 請求前先發起一個GET請求(GET請求不需要經過CSRF檢查)獲取CSRFToken並將響應中的CSRFToken添加到新的請求頭中。(推薦)
★ 解決思路
-
方案二
-
步驟一: 在返回給瀏覽器(客戶端)的響應中設置 csrftoken相關的 Cookie信息(需要保證csrftoken在有效期內)
-
步驟二:在發送請求前獲取最新的CSRF token,並且在前端的每次請求中都包含了這個token
// 首先,獲取CSRF token function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); // 假設CSRF cookie名為csrftoken if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } const csrftoken = getCookie('csrftoken'); // 然後,配置axios全局預設值 axios.defaults.headers.common['X-CSRFToken'] = csrftoken; axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; // 之後,所有通過axios發送的請求都會自動攜帶CSRF token
-
-
方案三
-
步驟一: 使用請求攔截器在每次 POST、PUT 或 DELETE 請求中前先發起一個GET請求獲取CSRF token 添加到請求頭中
// frontend.js import axios from 'axios'; const api = axios.create({ baseURL: '/api/', headers: { 'Content-Type': 'application/json' } }); api.interceptors.request.use(async config => { const { method } = config; if (method === 'post' || method === 'put' || method === 'delete') { const csrfToken = await getCSRFToken(); config.headers['X-CSRF-Token'] = csrfToken; } return config; }); async function getCSRFToken() { const response = await axios.get('/get-csrf-token/'); return response.data.csrfToken; } async function postData(url = '', data = {}) { const response = await api.post(url, data); return response.data; } postData('data/', { key: 'value' }) .then(data => { console.log(data); });
-
步驟二: 在Django後端中使用 Django REST framework 編寫了類視圖,實現返回csrftoken的邏輯
-
視圖views.py
# views.py from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from django.middleware.csrf import get_token class CSRFTokenView(APIView): def get(self, request): csrf_token = get_token(request) return Response({'csrfToken': csrf_token}) def post(self, request): # 處理 POST 請求的邏輯 return Response({'message': 'Data received'}, status=status.HTTP_200_OK)
-
路由urls.py
# urls.py from django.urls import path from .views import CSRFTokenView urlpatterns = [ path('get-csrf-token/', CSRFTokenView.as_view(), name='get_csrf_token'), path('api/data/', CSRFTokenView.as_view(), name='post_data'), ]
-
代碼說明:
在這個完整的示例中,前端代碼使用 axios 創建了一個名為 api 的實例,並通過請求攔截器自動添加 CSRF token 到請求頭中。後端使用 Django REST framework 編寫了類視圖 CSRFTokenView,其中包含了獲取 CSRF token 和處理 POST 請求的邏輯。最後,在 urls.py 中設置了兩個路由,分別映射到獲取 CSRF token 和處理 POST 請求的視圖函數。
-
-