#討論 django + React,CSRF 問題

如題 前端在localhost,是http://localhost:3000 後端在aws ec2上,是 http://<ipv4 address>:8000 - 問題: 在前端發送 POST requests 到後端的時候,如果啟用 django 的 CSRF Middleware django 就會報error:Forbidden 403 (CSRF cookie not set.) 但是如果不開CSRF Middleware就可以正常運作。 為了資料的安全性,我還是打算開 CSRF(當然最後如果還是無解那我也沒辦法⋯⋯) - 目前嘗試手段: ▪後端django settings.py: ▍CORS_ALLOWED_ORIGINS = ["http://localhost:3000", f"http://{HOST_AWS_EC2}"] ▍CORS_ALLOW_CREDENTIALS = True ▍CSRF_TRUSTED_ORIGINS = ["http://localhost:3000", '<ec2 ip address>'] ▍ALLOWED_HOSTS = [ 'localhost', '<ec2 ip address>' ] ▍CSRF_COOKIE_NAME = "csrftoken" ▍CSRF_COOKIE_SAMESITE = "None" #開發環境設置為none ▍CSRF_COOKIE_SECURE = False ▍CSRF_COOKIE_HTTPONLY = False ▍CORS_ALLOW_HEADERS = [ "content-type", "X-CSRFToken", ] ⋯ 後端api的部分也已經加了getCSRFtoken的api 前端也有在首頁就先打getCSRFtoken這支api,確認在storage→cookie,有一個後端域名的csrftoken 但就是在post requests的時候, document.cookie是空的。 getCookie()拿不到document.cookie 於是header沒有帶到cookie 所以 POST requests的CSRFToken=null 最後被django擋下來 ps.但同時,我確定application>storage>cookie裡面有域名來自後端的csrftoken 以下是前端的code:
megapx
⋯ 解這個問題一整天了,基本上django該設定的我應該都有設定⋯⋯ 唯一有問題的是以下這兩個 ▍CSRF_COOKIE_SAMESITE = "None" ▍CSRF_COOKIE_SECURE = False 因為CSRF_COOKIE_SECURE 要設置成false的條件,好像必須在https環境下 那在http的情況下,這個問題是否無解了? 要嘛我把前後端都設定成https,要嘛我把csrf middleware關掉? 雖然最主要的問題是,我不知道為什麼瀏覽器cookie中明明有後端的 csrftoken,但是POST requests的時候header卻不會自動攜帶後端的csrftoken⋯⋯
留言
你的cookie是設失敗的,這邊就可以看到Set-Cookie那欄的最右邊有驚嘆號:
megapx
chromium核心的瀏覽器你可以看到cookie是因為他也會顯示有問題的cookie,點選上面的「只顯示有問題的Cookie」你會發現csrftoken還會在。
megapx
至於失敗的原因很簡單,你為了實現跨域的cookie設定,設定了CSRF_COOKIE_SAMESITE為None,代表返回的Set-Cookie header中的SameSite為None,但要使用SameSite=None有一個條件要滿足,那就是安全連線,也就是前端請求後端設定csrftoken的api必須要設定Secure參數,且走https協議才行,否則這個Set-Cookie會被視為無效。請參考: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#none 再來說解決方式,最簡單的就是後端增加tls的設定(你可以直接套Cloudflare proxy),讓網頁改走https的方式來請求api,並啟用CSRF_COOKIE_SECURE;另外一種,是讓後端和前端的server都放在同一個域名底下(localhost、127.0.0.1也行,但前後端一定要使用同一種才行),並將SameSite設為Strict或Lax,這樣就不要求啟用tls,前後端不同port也沒差,Set-Cookie只要求domain和path(可選)而已。
B9(已編輯)