Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
demo 須知
Same Origin Policy
What is "Origin"?
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
See also
Basic Rules
- 所謂的「同源 (Same Origin)」是指兩個網站的「通訊協定 (protocol)」、「主機名稱 (hostname)」與「埠號 (port)」皆相同
- 網頁安全模型,在原則上,不同源的網站之間不允許通訊,以保障最基本的網路安全
- 給定
http://store.company.com/dir/page.html
,以下各 URLs 與之同源與否:
- ✅
http://store.company.com/dir2/other.html
- ✅
http://store.company.com/dir/inner/another.html
- 📛
https://store.company.com/page.html
- 📛
http://store.company.com:81/dir/page.html
- 📛
http://news.company.com/dir/page.html
- 但實際的預設規則是
- 透過 HTML tag (embedding) 內發起的 GET 請求,就算非同源,通常都會被允許
- 透過 Javascript 程式碼去發起的請求,都會被限制
- 以下以一份 HTML (source) 示範 tag 會被允許、而 JS code 會被 CORS 阻擋的例子:
demo steps
make run-same-origin-policy-demo
- open localhost:3000
- open DevTool and see the console
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
See also
Cross-Origin Resource Sharing (CORS)
- 前面示範了一個用 Javascript 執行「跨來源 HTTP 請求」,並且被瀏覽器預設的 CORS policy 擋下來的例子:
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
解法是什麼呢?
- 若想要你的 website 能夠取得其他來源的伺服器資源,會需要該伺服器回傳指定的 HTTP headers,以讓瀏覽器檢查伺服器回傳的 HTTP headers 是否符合 CORS 標準
那伺服器應如何實作此種白名單機制呢?
- 還需要了解,瀏覽器會對跨來源 HTTP 請求分成兩種情境、皆有不同的 CORS 驗證行為:
- Simple requests (簡單請求)
- Preflighted requests (預檢請求)
- 伺服器需要對不同情境具體地做出正確的實作,以滿足瀏覽器的要求
See also
Simple Requests
- 你發起的請求只是
GET
與 POST
、且沒什麼特別的 headers 時,瀏覽器會幫你執行 simple requests
- 此時,瀏覽器真的會發送請求給伺服器,並在拿到 response 後檢查伺服器是否允許此網頁存取它
- 檢查方式為查看 response header 中的
Access-Control-Allow-Origin
是否與網頁的 origin 相符合
- 若不符合,就顯示
blocked by CORS policy
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
demo steps
make run-simple-request
and start live coding
- 實作 endpoint,只 echo request headers
- go to https://example.com/ and open DevTool
- 發起
GET
請求,製造一個 simple request,呈現 blocked by CORS
- 完善 endpoint (
res.setHeader("Access-Control-Allow-Origin", "https://example.com")
),以允許網頁存取
See also
Preflighted Requests
- 其他會對 server data 產生 side-effects 的請求,CORS 規範要求瀏覽器必須
- 先 preflight a request 詢問伺服器:這是我接下來要傳送的 requests 摘要,請問允許嗎?
- 若允許,才執行真實的 request
- 所以一個 preflighted request,實際上會對伺服器發送 2 次 requests 來完成網頁的需求
瀏覽器 preflight a request 是什麼意思呢?
- 發送一個 HTTP
OPTIONS
請求給伺服器,並校驗伺服器的回傳
其中包含兩個 Access-Control-Request-*
headers:
Access-Control-Request-Method: <method>
描述真實請求的 method
Access-Control-Request-Headers: <field-name>[, <field-name>]*
描述真實請求中會帶入哪些 headers
伺服器應如何正確回應 OPTIONS
請求給瀏覽器呢?
- 針對那些預期會被非同源存取的 endpoint,具體實作
OPTIONS
的回應
伺服器得回傳一些 Access-Control-Allow-*
headers 資訊讓瀏覽器校驗:
Access-Control-Allow-Origin: <origin> | *
Access-Control-Allow-Methods: <method>[, <method>]*
Access-Control-Allow-Headers: <header-name>[, <header-name>]*
一個 Preflighted request 完整的循序圖
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
demo steps
make run-preflighted-request
and start live coding
- 實作一個
POST
endpoint 先滿足 simple request,then go to https://example.com/ and open DevTool
- 將請求改成:
POST
+ Content-type: application/json
,製造出 preflighted request
- 實作
options
endpoint,從伺服器端看到瀏覽器真的發起了一個 HTTP OPTIONS
請求
- 完成
options
endpoint,使伺服器正確回應瀏覽器的 preflighted request
See also
Practical Discussions
🤔 Should I implement CORS support from scratch on server-side?
- 當然找找與你使用的 web framework 最契合的 library/package,配置設一設就好囉
See also
🤔 Can we allow multiple origins?
Access-Control-Allow-Origin
並不支援回傳多個 origins 的語法 (無論你空白分隔還是逗點分隔,瀏覽器都不理你)
- 🛑
Access-Control-Allow-Origin: foo.com bar.com
- 🛑
Access-Control-Allow-Origin: foo.com, bar.com
- 也無法透過設置多個
Access-Control-Allow-Origin
在 response header 中來達成
- 建議的做法是伺服器檢查
Origin
是否在你的白名單
- 是的話則在
Access-Control-Allow-Origin
中填入該 Origin
See also
📝 Google Cloud Storage (GCS) needs CORS setting
- 我們會把檔案、圖片放到 GCS 內指定的 bucket,且可以取得一個 public URL 來指向該檔案
- 如果該檔案是一個圖片檔,實務應用會將它直接塞進
<img src="image link">
tag 裡,讓瀏覽器直接發出請求、拿到圖片、直接呈現
- 但 GCS 預設也不是任何人拿到 URL 都可以存取資源,它會要求你替該 bucket 設定好 CORS,正向表列出有哪些 websites 可以存取你的資源
See also
📝 CORS-RFC1918: protect users from cross-site request forgery (CSRF) attacks targeting routers and other devices on private networks
- 前面的 demo ,都刻意在 https://example.com 上,向本機伺服器 (
localhost:8080
) 發起請求

- 但如果你使用 Chromium-based browser 在 http://example.com 上發起,就會出現以下的 CORS 警示
- 因為,這個行為太像是一種低階的 Cross-site Request Forgery (CSRF)!
- 會出現 CORS 警示,其機制是因為 Chromium-based browser 實作了 CORS-RFC1918,目的是要保護運行在私有網路的服務、設備,不容易被用戶代理 (user agent, i.e. browser) 利用、攻擊
- Chrome 除了已限制網站向私有網路發起請求的能力 (since Chrome 9x),並計畫自 Chrome 102 起擴充 CORS 的驗證行為,在 public to private 的 CORS 請求中增加
Access-Control-Request-Private-Network: true
,並期待私有網路內的伺服器明確地回應 Access-Control-Allow-Private-Network: true
,才允許 CORS
See also
References