iT邦幫忙

2023 iThome 鐵人賽

DAY 11
0
Cloud Native

2023 年了,一起來學 CDN - 你也可以瞭解的 CloudFront 系列 第 11

Day 11 - 讓 CloudFront 跟 S3 正確回應您的 CORS 請求

  • 分享至 

  • xImage
  •  

跨來源資源共用 (CORS, Cross Origin Resources Sharing) 也是許多人會使用的功能,

也是很多人用 CDN 時遇過的坑

所以,我們今天透過這文章跟一起分享,如果用 CloudFront + S3提供內容時,要如何設定讓 CF 可以正確回應 CORS 請求。

首先,我先假設你已經看了先前介紹 Day 08 - 聽說可以直接拿 S3 當源站,該怎麼做?
已經可以將 S3 作為 CDN(CloudFront) 的源站,並且你有了一個測試的 URL,如下。

測試 URL: https://ironman.kgg23.com/TTFB.png

你希望在另一個網頁中引入這圖片,然後,然後他就失敗了。
https://ithelp.ithome.com.tw/upload/images/20230913/20162502jyWnD0AQcM.png
對,HTTP Status=200,然後報錯,
難道是傳說中的 手術成功,病人死亡 請求因未滿足 CORS 而被阻攔

入門版解釋 CORS 運作機制

  1. 考慮安全,瀏覽器對非目前同一域名的請求,會有嚴格的安全檢查。
  2. 檢查方式: 請求的網址回覆時,回覆需要帶有可以「同意被引用」的標頭。
  3. 檢查通過的才呈現,檢查失敗的不給看(a.k.a. 報錯)。

一開始遇到的 HTTP Status=200 的報錯,其實就是因為檢查時失敗。
所以,讓我們繼續在 Developer Tools 中點開當時請求的回覆。
https://ithelp.ithome.com.tw/upload/images/20230913/20162502vUpgZRzY1q.png

那麼,需要哪些標頭呢?

  • 為了能讓 S3 正確回應 CORS 標頭,一般來說會僅需要 'Origin' 這個標頭。
  • 但如果是瀏覽器在處理 CORS 請求前為了進行 'PreFlight' Check(飛行前檢查),瀏覽器會以 'Options' 這 HTTP Method送出,那麼還需要另一個標頭,'Access-Control-Request-Methods'

好難懂,可以先說該怎麼設定,之後再說原理嗎?

當然可以,今天的文章先介紹如何設定,作法如下:

  • 架構: Client --> CF --> S3
  • 修改 S3 設置,在 S3 bucket 的 CORS 設定中貼上以下內容。
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "PUT",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]
  • 修改 CloudFront 的 Behavior 設定,在 'Allowed HTTP methods' 的部分,選為 'GET, HEAD, OPTIONS'
    https://ithelp.ithome.com.tw/upload/images/20230913/20162502cIZFUpZY4R.png
    這時再次測試,就看到已經可以正常取得回應。
    https://ithelp.ithome.com.tw/upload/images/20230914/20162502BHr22ExkJA.png

問題是怎麼解決的? 原理說明

前面提到,瀏覽器發出 CORS 請求時,會檢查回覆內容有無帶相關標頭。
所以,我們可以反過來想如何解決這問題。

  • 第 1 步,先確定 S3 可以正確回應 CORS 請求,返回必要的標頭。所以我們可以參考這份 S3 文件,將 CORS 相關設定加到 S3 Bucket 之中。
  • 第 2 步,確認 S3 要正確回應 CORS 請求,需要哪些資訊(收到的請求需滿足哪些條件)。我們參考這份 CloudFront 文件,注意到需要轉發 3 個標頭。
原始伺服器請求中包含的標頭:
- Origin
- Access-Control-Request-Headers
- Access-Control-Request-Method

完成上述設定後,針對 S3 的相關設置也就完成。

那麼,要怎麼測試 & 驗證呢?

測試方法 1: 從 developer console 中,針對目標網址發出請求。

  • 假設你先連到頁面: https://dwnhikcdqi4zf.cloudfront.net/ ,此時開啟 Developer Tools,在 console 輸入指令,fetch('目標URL'),以下以 'https://ironman.kgg23.com/TTFB.png' 作為測試目標
fetch('https://ironman.kgg23.com/TTFB.png')
  • 檢視 Developer Console 有無報錯,以及點選剛的請求看返回的內容。
    https://ithelp.ithome.com.tw/upload/images/20230914/20162502BHr22ExkJA.png

測試方法 2: 透過 curl 指令測試。

  • 我們可以直接透過 curl 指令 + 參數的方式來測試 CORS 的設定,判斷有無看到 'access-control-allow-origin' 以及 'access-control-allow-methods'的回應。如果有,就代表此時已經有得到正確的 CORS 回應。參考指令 & 回應如下
$ curl -svo /dev/null "https://ironman.kgg23.com/TTFB.png" -H 'Origin: http://www.google.com'
< HTTP/2 200
< content-type: image/png
< content-length: 256325
< date: Wed, 13 Sep 2023 16:24:29 GMT
< access-control-allow-origin: *
< access-control-allow-methods: GET, PUT, POST, DELETE
(其餘標頭先省略) 
< vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
< x-cache: Miss from cloudfront
< via: 1.1 4e7b30670ccb8a3f3101333ef882f9b0.cloudfront.net (CloudFront)
< x-amz-cf-pop: TPE51-C1
< alt-svc: h3=":443"; ma=86400
< x-amz-cf-id: cAVcEzfu92832GENaZQKPatthNF7d1L5NgLF2R90pKEc-12ff5M27Q==

https://ithelp.ithome.com.tw/upload/images/20230914/20162502D6Z0eBqNak.png

或者,您也可以參考這影片,這影片也講得很清楚 (笑 & 深深相信)
Yes

額外練習:

請問,還有其它作法,讓 CORS 請求的內容可以順利呈現的方式嗎?
歡迎在留言區跟我分享你的作法

Okay, let's call it a day. 今天的文章先到這裡,我們明天見。


可補充的資料:


上一篇
Day 10 - 我可以控制 CloudFront 中的檔案可以用多久嗎?
下一篇
Day 12 - 來聊聊 CloudFront 的 Origin
系列文
2023 年了,一起來學 CDN - 你也可以瞭解的 CloudFront 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言