一句話:單純的 presigned PUT 綁不住「上傳內容」(body 沒被簽),想限制大小/型別用 POST policy,想在 bucket 層劃永久硬線(如強制 HTTPS)用 bucket policy。
回想 Level 3:presigned URL 的 payload 是固定字串 UNSIGNED-PAYLOAD——body 根本沒被簽進去。所以拿到一條 presigned PUT URL 的人,可以在期限內上傳任何內容、任何大小。這就是安全缺口:你沒辦法靠這條 URL 本身限制「只能傳 5MB 以下的 JPEG」。
改用 HTTP POST(browser-based upload)搭配一份 policy 文件,明訂條件,S3 會強制檢查、不符就拒:
uploads/用戶ID/);這正好補上 presigned PUT「內容不設限」的洞——想讓前端直傳、又要卡大小/型別,就用它(Level 6 會細講 POST policy 的做法)。
bucket policy 是 bucket 層級的規則,不管誰、用什麼 URL 來,這條線都不能越。最常見的加固:
aws:SecureTransport = false 的請求,防止 URL 走明文 HTTP 被中途竊聽。pre-signed URL:管「誰能在多久內做這個動作」。
POST policy:管「上傳的內容要符合什麼條件」。
bucket policy:管「這個 bucket 永遠不允許什麼」。
三層疊起來,才是穩的直傳方案——不要只靠一條 presigned PUT 就想擋住所有壞情況。