iT邦幫忙

2026 iThome 鐵人賽

DAY 16
0
IT Operation

從前後端踏上 AWS 雲端架構勇者之路系列 第 16 篇

同一張 S3 圖片,為什麼 Allow 了還是看不到?

  • 分享至 

  • xImage
  •  

上一篇我們把圖片上傳到 S3,也拿到了圖片網址

但如果把網址貼給朋友,卻看到 AccessDenied,奇怪,圖片不是已經傳好了嗎?

因為你能上傳,跟別人能不能看,是兩件事。S3 還沒允許其他人讀這張圖片

今天就接著把圖片開放給別人看,再把它關回來,讓你能多瞭解 S3 的權限設計~

我們來回到全貌圖,今天看橘色這條線:瀏覽器直接向 S3 讀圖片。這段沒有經過 EC2,所以這次要改的是 S3 的設定,不用動主機的 Security Group

瀏覽器直接用 Object URL 向 S3 讀取圖片,今天檢查 S3 的 Bucket Policy 與 Block Public Access,EC2 不在這次讀圖路徑上

為了能看到圖片資料,我們會用 Bucket Policy(儲存桶政策) 寫下「允許任何人讀這張圖」

但 S3 還有 Block Public Access(封鎖公開存取)。如果它擋住公開讀取,就算 Policy 寫了允許,朋友還是看不到。接著就來試試這兩個設定

開始開幹!

沿用上篇的練習 Bucket,裡面放一張可以給大家看的 practice/sample.png。ACLs disabled、SSE-S3 都維持原設定,Bucket Policy 目前也是空的

這次除了上傳,還會修改 S3 的政策與封鎖設定,所以先確認自己的 IAM User 有這些權限,當然用 root 練習也是可的

取消封鎖,圖片就公開了嗎?

還沒喔,取消封鎖後,還要告訴 S3,這張圖片可以給誰看

這裡有個容易漏掉的地方:AWS 帳號可以統一封鎖底下的 Bucket。如果帳號這邊還擋著,只改 Bucket 也沒用,所以我們先看帳號設定

1. 確認帳號沒有擋住這次練習

到 S3 → Account and organization settings → Block Public Access settings for this account,先記下原設定,最後要再恢復過來

我們用 Bucket Policy,相關的是下面兩項。畫面上的說明都含有 public bucket or access point policies:

設定名稱 勾選後會怎樣?
BlockPublicPolicy 不讓你存入會公開的 Bucket Policy
RestrictPublicBuckets Bucket 已有公開 Policy 時,還是會擋住匿名讀取

這兩項已關閉就不用改。有勾選的話,先確認這是自己的練習帳號,而且其他 Bucket 不會跟著公開,再來按 Edit 取消這兩項

接著按 Save changes,依畫面輸入 confirm 儲存。這是在改整個帳號的設定,其他 Bucket 也會受影響

2. 取消這個 Bucket 的封鎖

回到練習 Bucket 的 Permissions → Block public access (bucket settings) → Edit

取消 Block all public access,確認下方四項都未勾選,再按 Save changes,依畫面輸入 confirm 確認

取消練習 Bucket 的 Block all public access,四項均未勾選

現在用新的無痕視窗打開原本的 Object URL,應該還會是 AccessDenied。因為我們只取消封鎖,還沒寫下允許誰讀取

接下來讓別人讀這張圖,要怎麼調整設定?

到同一個 Permissions → Bucket policy → Edit,貼上以下內容,把 YOUR_BUCKET_NAME 換成自己的 Bucket 名稱:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadPracticeImage",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/practice/sample.png"
    }
  ]
}

這條規則合起來就是:允許任何人讀取這個 Bucket 裡的 practice/sample.png

欄位 這次代表什麼?
Effect: "Allow" 允許
Principal: "*" 任何人,包含沒有登入 AWS 的網友
Action: "s3:GetObject" 讀取 S3 物件內容
Resource 只指定這張圖片,包含完整 Key

Resource 要填的是 AWS 用來辨認這張圖片的名稱,這種寫法叫 ARN。所以前面是 arn:aws:s3:::,後面接 Bucket 名稱與完整 Key

這次只想開放一張圖,就保留 practice/sample.png。如果把這段換成 *,就會變成允許讀取整個 Bucket 裡的物件

確認後按 Save changes。這條規則只有讀取,沒有允許網友上傳、刪除或列出其他檔案。也附上(Bucket Policy 說明、公開讀取範例)

再來開同一個網址看看

從圖片的 Properties → Object URL 複製網址,關閉所有無痕視窗,再開新的無痕視窗貼上

照前面的設定做完,沒有其他限制的話,這次應該就看得到圖片了

你會發現,圖片沒重傳,網址也沒換

這裡複製 Object URL。Open 按鈕提供的連結可能帶有暫時的讀取權限,用它開得了圖片,不過這還不能證明一般網友也能看(官方說明)

如果還是看不到,先檢查 Policy 有沒有存成功、Bucket 名稱與 Key 有沒有寫對,再看帳號與 Bucket 是否還擋著公開讀取

接著我們把封鎖打開,看看會發生什麼事?

回到 Permissions → Block public access (bucket settings) → Edit,重新勾選 Block all public access,確認四項都勾選,儲存

重新勾選 Block all public access,四項均勾選

先保留下方的 Policy,不要刪除。然後關閉所有無痕視窗,再開新的無痕視窗,貼上剛才同一個 Object URL

這次應該又會看到 AccessDenied (該不會是在耍我

咦,Policy 裡不是還寫著 Allow 嗎?

因為 Allow 還在,但我們把公開讀取擋回去了。剛才勾選的 RestrictPublicBuckets,會擋住這種沒有登入 AWS、直接用網址讀取的請求。但 Policy 並沒有被刪掉

也幫大家把剛才的過程整理成一張圖,方便對照

同一張圖片在 Bucket 封鎖與公開 Policy 的四種組合下,新的匿名請求依序被拒絕、被拒絕、可讀、再被拒絕

如果舊分頁還看得到,記得換新的無痕視窗再試。圖片已經載入或下載到別人的電腦,不會因為你改權限就消失;要重新向 S3 讀取,才看得出差異

客戶要上傳圖片,也要讓 Bucket 公開嗎?

不用的。前面是練習讓任何人讀一張圖片,實際做網站時,也可以讓 Bucket 保持私有

這裡拿一般平台流程來分享:使用者在網頁選好圖片,先向後端請求上傳。後端確認可以後,才給他一個有期限的上傳網址,叫做 預簽名 URL(Presigned URL)

這個網址是後端用自己的 AWS 身分產生的,會指定要上傳到哪個 Key。當然,後端自己也要有上傳到那個位置的權限,也附上(官方上傳說明)

整個流程可以看下面這張圖:

後端驗證身分並提供預簽名 URL,瀏覽器直傳私有 S3,完成後由後端查核檔案並記錄 Key

重點會在第二段:瀏覽器拿到網址後,圖片直接傳到 S3,不用先傳到我們的後端主機

那 S3 怎麼知道這個人能不能上傳?它會檢查網址的簽名與 AWS 權限。至於這個人有沒有登入網站、能不能上傳,前面就得由後端確認好

而且前端說「傳好了」,後端也不能直接當作完成。還要去確認,傳的是不是剛才允許這位使用者上傳的那個檔案、檔案是否真的存在且符合要求,再把 Key、檔案是誰的、是否上傳完成,記進資料庫

那上傳完,前端要怎麼顯示圖片?

如果圖片只想給特定使用者看,後端先確認他能看,再給另一個有期限的讀取網址。剛才拿到的是上傳用的,不能直接拿來讀圖

所以資料庫會保留圖片的 Key,需要時再產生新的連結,不會只存一個過期就不能用的網址

要提醒一下,有期限不代表只能用一次,也不代表只有原本那個人能用。網址被轉傳,拿到的人在它有效時也可能使用,所以期限只給這次操作需要的時間

真正接到前端時,還要設定 CORS,讓瀏覽器允許網站向 S3 發出這類請求。至於能不能上傳,也要檢查前面講的權限,設定 CORS 不會自動取得上傳權限

圖片網址可以換成自己網域的嗎?

剛才 S3 給我們的網址,大概長這樣:

https://my-site-images.s3.ap-northeast-1.amazonaws.com/practice/sample.png

光看網址就知道圖片放在 AWS,那如果想換成自己網站的名字呢?

https://images.example.com/practice/sample.png

這段是可以的,AWS 有個服務叫 CloudFront,就能幫我們做到這件事。圖片照樣放在 S3,由 CloudFront 拿給網友看。拿過的圖片也能先留一份,下次有人要看,就不用每次都回 S3 拿

設定時,要把 CloudFront 接到自己的 S3,再設定網域與 HTTPS 憑證,這裡附上 設定教學

如果你是無課金玩家,也可以用 Cloudflare R2 的免費額度來練習。R2 是另一個放檔案的地方,所以圖片要改傳到 R2,做法大概是:

  1. 開通 R2,建立 Bucket,把可以公開的圖片傳上去。
  2. 把自己的網域加入同一個 Cloudflare 帳號。
  3. 到 Bucket 的 Settings → Custom Domains 設定圖片網域,就能用自己的網址讀圖了(設定教學)。

免費額度有上限,超過還是會收費,也附上(R2 價格)

兩種做法整理如下,主要看右邊,圖片是放在 S3 還是 R2:

用自己的網址看圖片:上面放在 S3,透過 CloudFront 讀取;下面放在 R2,透過 Cloudflare 讀取

小結

最後總結一下:

重點 記住這句
自己的 IAM 權限 決定自己能不能管理 S3,不等於替網友授權
Bucket Policy 寫清楚誰、可以做什麼、對哪個物件
取消公開封鎖 還要有公開授權,圖片才會讓網友讀取
Policy 寫 Allow 還要看有沒有適用的封鎖或其他限制
收尾 重新封鎖,再移除這次的公開規則

希望這篇有讓你對 S3 的權限更有概念,我們下篇見 :D


上一篇
圖片一定要放在 EC2 裡嗎?認識 S3、Bucket 和 Object
下一篇
會員資料與訂單放哪裡?來認識 RDS~
系列文
從前後端踏上 AWS 雲端架構勇者之路 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言