作者: HannahLin
來源:medium
有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。
我相信每一個前端在對接 API 時,多多少少一定遇過以下錯誤:
雖然要解決此問題大部分還是需要後端幫忙,但前端也需要知道為什麼會發生、要如何解決。
同源政策 (Same Origin Policy)
同源政策是網站安全的基礎。 https://domain-a.com 只能存取自己網站裡的資源 (圖片、影片、原始碼代等),不允許網站 https://domain-b.com 來存取。想要存取跨來源資源必須在某些特定情況下才被允許。
畫清楚界線自己網站自己管,別人讀取不到也改不了。這很合理,不然若自己網站被別人任意修改、被惡意人士讀取機密資訊那就糟糕了!若沒有這層防護,壞人就可以任意新增刪除我們在各大社群裡面留言了、也可以輕易登入我們的銀行帳戶 ?。
怎麼判斷同不同源?
只要 scheme
、domain
、port
一樣就會被視為同源 (same-origin
),其他則是不同源
若以 https://domain-a.com:80/hannah-lin
做範例,我們可以因此判斷跟以下是否同源:
http://domain-a.com → 不同源.scheme 不同
https://domain-a.com/mike → 同源
https://news.domain-a.com → 不同源.domain 不同
https://domain-a.com:81 → 不同源.port 不同
https://domain-b.com → 不同源.domain 不同
Note. IE 對於不同 port
會視為同源
但我網站明明就引入很多跨來源的資源啊?
網頁常見的跨來源資源真的不少,例如以下:
沒錯,在某些情況下跨來源是被允許的,不受同源策略限制
跨來源嵌入通常被允許 (embed)
像範例的 <script src=”…”></script>
、<link rel=”stylesheet” href=”…”>
、<iframe>
、圖片 <img>
、<video>
、或是 @font-face <object>
、 <embed>
.等等都是跨來源嵌入。
跨來源寫入通常被允許 (writes)
可以在藉由 <form>
在 domain-a.com
發 request 給 domain-b.com
,當然透過連結 links
或直接 redirect
到別的網站也是被允許的。
跨來源讀取通常被禁止 (reads)
domain-a.com
不能讀取 domain-b.com
的 cookie、XMLHttpRequest ,Fetch API 也都無法被讀取,會回報錯誤:
同源政策 (Same Origin Policy) 允許 HTML tag 產生的跨來源寫入 (write)/嵌入 (embed)/讀取 (read),但對於 JS 的跨來源 write/embed/read 是有限制的。
那什麼是 Cookie 的同源 ?
Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: id=1234567; domain=hello.com
前端都知道 Cookie 是什麼,簡單來說就像一張通行證,通行證裡面會存有一組 Session ID 來驗證你身份,就像你加入某某俱樂部一樣,認卡不認人,誰擁有這張通行證就可以進入俱樂部。
Cookie 的同源跟以上所說的 DOM 同源有點不同 (圖片或是原始碼等資源被載入瀏覽器最後都會變成 DOM 的元素)
只要 domain 跟 Path 與 Cookie 上的一樣就會被視為同源。若經過一些設定才會判斷 scheme 要是 http 或 https。
// 加了 Secure 會限定此 Cookie 只能以 https 傳送
Set-Cookie: id=1234567; domain=hello.com; Secure
另外要注意的是子網域的 cookie 是可以存取到母網域 cookie 的 (api.domain-a.com 跟 domain-a.com cookie 可以被共用)
對了,同源政策是瀏覽器專屬,所以才會發生用 postman 可以拿到 API 回應但放到網站上就是會失敗的狀況。
CORS (Cross-Origin Resource Sharing)
CORS 翻成中文就是跨網域資源共享,也就是你可以用我資源我也可以用你的
為什麼會有 CORS
Same Origin Policy 雖然不錯,因為他防止了一些惡意的 script
攻擊,但總不會每一個跨網域都是惡意的; 也不可能一間公司擁有所有的資源,有時還是必須串接第三方資源,例如 Facebook API、Google Map、政府提供的公開 API 等。
怎麼設定
設定 CORS 相當容易,它其實只是 HTTP-Header
而已,這些設定基本上都是在後端,所以前端只需知道概念跟怎麼看 Responce Header 即可。
當前端用 fetch
或 XMLHttpRequest
要存取資源時,在 request
之前都會先傳送 preflight request
確定 server
端有設定正確的相關 Http-Header
,若檢查通過,才會實際發出 requeest
。例如
fetch('https://xxx.com/data/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
})
那 request header 會大概長這樣
POST /data/
Host: xxx.com
Origin: https://myweb.com
Content-Type: application/json
preflight reques 會大概是這樣:
OPTIONS /data/
Host: xxx.com
Origin: https://myweb.com/
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
可以在 developer tools 中的 Network 看到相關的 Responce Header
當然後端可以把許可權開到最大讓任何人都可以讀取,不受同源政策的限制
Access-Control-Allow-Origin: *
但跨來源還是有許多風險的,所以建議還是不要直接 *
。
// 還是會針對特定網站開許可權
Access-Control-Allow-Origin: https://foo.example
// 可以設定允許哪些 method,defult 是全部方法
Access-Control-Request-Method: POST, GET
// 允許 client side 帶 cookie 等驗證,defult 是 false
Access-Control-Allow-Credentials: true
preflight request?
不是 simple request 都會先發一個 preflight request 確定 server 端有設定正確的相關 Http-Header,也就是會先問 server 是否允許這個 request,允許的話才會正式 request。像 HTTP PUT/DELETE method
,或 Content-Type: application/json
都會先發 preflight request。
有同源政策的保護,我的網站就是安全的嗎 ?
答案:不能。
Same Origin Policy 只是最基本的保護而已,實際上 attackers 還是可以聰明地找到漏洞攻擊你的網站。例如 Cross-site scripting (XSS)
可以欺騙網站來繞過同源政策的保護,這是一個很大的問題,因為同源政策下瀏覽器信任底下所有資料存取都是安全的,但這樣被惡意注入利用很有可能就讓你網站掛掉,更嚴重是使用者敏感資料被洩漏,應該被保密的資料被壞人利用。
HTML5 Security Cheatsheet 這個網站蠻酷的,提供各種 XSS 變形手法程式以及範例可以上去玩玩看
要確保自己網站的安全,還是需要下功夫的,接下來也會介紹一些簡單的方法來保護你的網站!
程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
原文:https://medium.com/starbugs/%...
交流
有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq44924588... 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。