後端跨域 研習CORS 跨域 後端視角

2021-10-16 03:35:13 字數 4167 閱讀 8651

作為乙個後端開發,經常會把後端服務設定成允許跨越,如果是用django一般是+ 包外掛程式django-cors-headers。但是這樣有沒有安全隱患呢?拉上前端小夥伴又認真研習了一下~

首先得明白什麼是跨域。跨域對前端來說應該是非常熟悉的,指的是來自**a的js**訪問**b,即訪問了不同的源。同源定義是相同網路協議,相同網域名稱(含一二級網域名稱等全部),相同埠。

跨域攻擊的基本原理是,瀏覽器訪問**a,**a登入資訊等存在相應的cookie中(此處前端小夥伴說,cookie,storage等都是和網域名稱相關的,只有訪問同網域名稱的時候才能獲取到)。這時候使用者在另乙個頁卡開啟了**z,假如**z是乙個惡意**,植入了惡意js指令碼,這個時候這段惡意指令碼就可以帶著篡改過的資料,訪問**a,並帶上之前的cookie中a的登入資訊等。如果a是銀行**,z執行的惡意攻擊可能就是訪問a並把使用者的錢轉賬給其他不法賬戶。

如果上述a**伺服器不允許跨域,z的ajax請求訪問a的時候,因為不同源(必須同樣的協議比如https,同樣的網域名稱包括二級網域名稱都要相同,同樣的埠比如80),a伺服器就不會響應z的請求,也就保障了安全。

目前我們專案的配置是,普通使用者只能訪問**位址a(a是乙個純前端node應用) ,a網頁**裡ajax訪問網域名稱b(b是django寫的後端應用),登入b的方式是token認證,然後token存在瀏覽器。a伺服器是不允許跨域的(後續大家討論允許跨域也還是安全的),b伺服器是允許跨域的,返回header裡 access-control-allow-origin: * . 這樣為什麼是安全的呢?

瀏覽器請求到a的js,裡面ajax訪問b進行登入

獲取到b的token,存在local storage裡(關聯的是a網域名稱)

假如使用者開啟惡意**z

因為a伺服器禁止跨域,所以z無法請求a伺服器。所以是安全的。

如果z想拿著a的local storage裡的token去訪問b,因為token的源是a,所以瀏覽器限制了沒辦法拿到去訪問b。所以也是安全的。

那麼假設,a伺服器也設定了允許跨域。那麼z可以拿著token去請求a伺服器,但是因為token是b頒發的,所以請求a沒有任何意義。所以還是安全的。

這裡就不得不引入另乙個現實情況了——b的後端實現是django+drf。也就是提供服務端渲染的頁面,可以用session的方式登入。於是又腦洞大開,那如果在瀏覽器第乙個tab裡,先用session的方式登入b,然後在另乙個tab訪問惡意**z,由於b是允許跨域的,z是不是就可以用cookie裡的session訪問b了,是不是就會有問題了?

access-control-allow-origin: *。 很多人有疑問,寫*會不會不安全,如果只寫allow a會不會安全一些?實際並不是這樣。 當瀏覽器請求伺服器,第一次option請求的時候,伺服器返回response header access-control-allow-origin: * ,只有當值是*的時候,是不允許攜帶cookie的。回到上面假想的訪問b的時候用session的登入方式,會不會不安全?答案是安全的,因為access-control-allow-origin: * 要不就同源訪問,要是非同源的話是不允許帶cookie的。

是不是感覺清楚多了,完全明白了現在的伺服器允許跨域為什麼是安全的了。

小夥伴們又問了,為什麼現在都流行用token比如jwt取代session的方式登入呢?

作為乙個後端,我認為token對後端的改進是比較大的,因為如果用session的話,資料庫裡需要存session表,根據前端發來的session_id查表才能獲取到使用者。而token比如jwt,頒發之後就不需要再儲存了,校驗的時候只需要用secret加鹽校驗是自己頒發的有效token,再從token payload 取出使用者id就可以了。而對前端來說,存session_id和token,都是兩個字串,感覺沒什麼區別。

不過這麼想是*****了。實際上token在前端對比session_id還有另乙個好處,就是順便解決了csrf跨站請求偽造問題。當瀏覽器通過form表單提交伺服器的時候,cookie是被自動帶上的,且不遵循同源原則。也就是說,如果惡意**z的js通過form提交**a的伺服器,且篡改了提交資料,且登入a是通過session_id存cookie的方式,就可以達到文章開頭提到的轉錢給不法賬戶的效果。這個時候通常的解決方法是通過form攜帶csrf token,也就是表單每次提交的時候,都需要攜帶a伺服器分發的乙個csrf token,後端會校驗csrf token是否有效。這樣就能避免csrf攻擊了,因為z的js是無法自己獲取到乙個新的有效的csrf token的。那麼,如果不是用session的登入方式,而是用token authorization的方式,表單提交的時候自動帶上的cookie就沒用了。原理其實就類似csrf token,請求需要把jwt token從local storage取出來放在請求header裡。這樣流程就回到了文章上述的各流程中,也就避免了csrf攻擊。所以即使對前端來說,token登入方式也比session的登入方式更有優勢。

最後再看一下伺服器允許跨域是怎麼實現的。首先在settings.py 裡配置 cors_origin_allow_all = true 表示允許跨域。然後檢視** corsheaders/middleware.py 中 corsmiddleware 中

可以看到,如果設定允許跨域,response[access_control_allow_origin] = 「*「 這段**會設定header中的access_control_allow_origin為*,和我們實際檢視的response header對應上了。

前後端分離 跨域問題 CORS

1 cors是乙個w3c標準,全稱是 跨域資源共享 cross origin resource sharing 它允許瀏覽器向跨源 協議 網域名稱 埠 伺服器,發出xmlhttprequest請求,從而克服了ajax只能同源使用的限制。cors需要瀏覽器和伺服器同時支援。它的通訊過程,都是瀏覽器自動...

前後端通訊 CORS(支援跨域)

根據前端跨域的那些事這篇文章中的跨域的理解這一塊,我們重新建立兩個服務,第乙個服務使用了test.html test.html中使用fetch來傳送請求,並且設定了乙個自定義的請求頭 x test cors 123 測試body 第二個服務,還是設定了 access control allow or...

後端 跨域方式

複製下面 如果能獲得介面介面說明不存在跨域 doctype html en utf 8 viewport content width device width,initial scale 1.0 document title head script var url ajax error functi...