簡體   English   中英

CSRF和CORS與Django(REST框架)

[英]CSRF and CORS with Django (REST Framework)

我們正在將我們的前端轉移到一個單獨的項目(Django之外)。 這是一個Javascript單頁面應用程序。

其中一個原因是讓我們的前端開發人員更容易完成他們的工作,而不必在本地運行整個項目 - 包括API。 相反,我們希望他們能夠與我們設置的測試API進行通信。

我們已經設法解決了大部分CORS / CSRF問題。 但是現在我們遇到了一些我無法在任何地方找到解決方案的東西,盡管閱讀了大量文檔和SO答案。

前端和API由不同的域提供(在開發localhosttest-api.example.com期間)。 到目前為止,雖然從同一個域提供服務,但前端已經能夠從API(Django)設置的csrftoken cookie中獲取CSRF令牌。 但是,當從不同的域提供服務時,前端( localhost )無法訪問API的cookie( api-test.example.com )。

我正在試圖找到解決這個問題的方法,以某種方式將CSRF令牌傳遞給前端。 Django文檔建議為AJAX請求設置自定義X-CSRFToken標頭 如果我們在每個響應中以類似方式提供CSRF令牌作為標頭並且(通過Access-Control-Expose-Headers )允許前端讀取此標頭,我們是否會破壞CSRF保護?

鑒於我們已經為API正確設置了CORS(即只允許某些域對API進行跨域請求),第三方站點上的JS應該無法讀取此響應頭,因此無法做出妥協AJAX請求我們的用戶背后,對吧? 還是我錯過了一些重要的事情?

還是有另一種更好的方法來實現我們想要的東西嗎?

假設您已經安裝了corsheaders 編寫Django中間件並將其包含在MIDDLEWARE設置中:

from django.utils.deprecation import MiddlewareMixin

class CsrfHeaderMiddleware(MiddlewareMixin):
    def process_response(self, request, response):
        if "CSRF_COOKIE" in request.META:
            # csrfviewmiddleware sets response cookie as request.META['CSRF_COOKIE']
            response["X-CSRFTOKEN"] = request.META['CSRF_COOKIE']
        return response

在您的設置中公開標題:

 CORS_EXPOSE_HEADERS = ["X-CSRFTOKEN"]

當你從JS進行GET API調用時,你應該從響應頭獲取X-CSRFTOKEN ,當你發出POST PUT PATCH DELETE請求時,繼續將它包含在請求頭中。

我一開始並不理解您的問題,因此請允許我總結一下:您無法從客戶端上的cookie獲取CSRF令牌,因為同源策略阻止您訪問跨域cookie(即使使用CORS)。 因此,您建議服務器在自定義標頭中將cookie傳輸到客戶端,並且想知道這是否安全。

現在,如果你沒有使用cookie,那么文檔確實提出了如何傳輸令牌的建議: 把它放在響應體中 例如,您可以使用自定義meta標記。 在安全方面,我傾向於使用推薦的解決方案,而不是相信我自己對新事物的分析。

除此之外,我沒有看到你提出的任何安全問題。 同源策略將阻止第三方站點像正文一樣讀取標題,您可以選擇使用CORS Access-Control-Expose-Headers標頭從客戶端域讀取它們。

您可能會發現這個答案很有趣,因為它列出了各種CSRF令牌方案的優缺點。 它包括使用自定義響應標頭,並且 - 在您的問題點 - 確認:“如果惡意用戶嘗試在上述任何方法中讀取用戶的CSRF令牌,那么同源策略將阻止這種情況” 。

(您可能想要查看您的SPA是否需要Django的CSRF保護。例如,請參閱此分析 。但這不在本問題的范圍內。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM