#討論 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⋯⋯
愛心
13
38
全部留言
這則留言已被本人刪除
已經刪除的內容就像 Dcard 一樣,錯過是無法再相見的!
B1
這篇真的是最近以來最優質的發文了
確認看看是否有設定 httpOnly 這會讓javascript無法取得cookie (防止xss 所以不應該在前端打request的時候另外帶header 後端要直接拿cookie裡面的token
localhost
確認一下,你的後端在 ec2,然後你的前端在自己本機? 如果是的話,那 localhost 應該要改成你電腦的 ip 吧,不然localhost 讀到的是 ec2 的後端。 另外,如果很確定上線都會用 https,本地測試前端的時候可以用 ngrok,他會給你派一組 https url,把他加入 django 那邊的 CORS_ALLOWED_ORIGINS 這樣就可以省去 http 的問題。
可疑帳號
官方正在進行身份確認
啊沒事,你的 Origin 是 localhost
sticker
B6(已編輯)
可疑帳號
官方正在進行身份確認
因為妳想要用前端 JS 讀取 csrftoken cookie ,但此 cookie 是屬於 EC2 那台,由於 SOP 限制無法這麼做,也就是說 frontend.com 不能用 document.cookie 來讀取 backend.com 的 cookie 但是妳又有用 CORS credentials ,所以你的 POST request 還是會帶 cookie
更新一下,按照上面大家的建議,我後來在localhost開django後端和react前端 (因為想要簡化問題所以前後端都是在本地端測試) 後端:http://127.0.0.1:8000 前端:http://localhost:3000 django的設定也都加了public ip和privacy ip,如圖
megapx
但問題還是一樣⋯⋯ 1.getcsrf有拿到csrftoken,header有set-cookie
megapx
megapx
2.查看cookies有來自後端的csrftoken
megapx
3.但是發送post /submit/請求的時候,header沒有帶到csrftoken
megapx
megapx
還好看起來不是ec2的問題 因為就算前後兩端都在localhost也不行⋯⋯完蛋了啊啊啊這樣以後要怎麼在local開發Orz
B8(已編輯)
你的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(已編輯)