Artikel

Presigned URL S3: pengertian, cara kerja, batas masa berlaku dan contoh kode

Apa itu presigned URL S3, arti setiap parameter X-Amz, batas 7 hari, kode unggah dan unduh (CLI, boto3, JS) serta solusi error yang umum.

Presigned URL S3 adalah tautan sementara ke satu objek di bucket privat. Tautan ini membawa tanda tangan di query string-nya, sehingga siapa pun yang memegangnya dapat mengunduh (atau mengunggah) objek tersebut tanpa kredensial AWS hingga tautan kedaluwarsa, dan bucket tidak pernah menjadi publik. Anda membuatnya dengan key Anda sendiri, di kode Anda atau dari AWS CLI, dan masa berlakunya bisa dari 1 detik hingga 7 hari. Panduan ini membahas cara kerjanya, arti setiap parameter X-Amz-*, berapa lama tautan dapat bertahan, kode untuk unduhan dan unggahan serta error yang paling mungkin Anda temui. Batas-batasnya diambil dari dokumentasi AWS dan Cloudflare per Oktober 2026.

Sekilas presigned URL S3

PertanyaanJawaban
Apa yang diberikannya?Satu operasi (GET, PUT, HEAD, DELETE…) pada satu objek
Masa berlaku maksimum7 hari (604.800 detik) dengan SigV4 dan key pengguna IAM
Masa berlaku dengan key sementaraBerakhir saat sesi role atau kredensial STS berakhir, mana yang lebih dulu
Rentang di konsol S31 menit hingga 12 jam
Masa berlaku default3.600 dtk di AWS CLI dan boto3, 900 dtk di presigner JavaScript v3
Bisakah digunakan beberapa kali?Ya, sesering apa pun hingga kedaluwarsa
Bisakah satu URL dicabut?Tidak, hanya dengan mencabut kredensial penanda tangan atau menolaknya di kebijakan
Apakah membuatnya memanggil S3?Tidak, tanda tangan dihitung secara lokal

Cara kerja presigned URL

  1. Kode Anda (atau CLI) mengambil bucket, key objek, metode HTTP dan waktu kedaluwarsa.
  2. SDK menandatangani nilai-nilai tersebut dengan secret access key Anda menggunakan AWS Signature Version 4. Belum ada yang dikirim ke S3 pada tahap ini.
  3. Anda memberikan URL yang dihasilkan kepada seseorang: browser, rekan kerja, aplikasi seluler.
  4. Saat mereka menggunakannya, S3 menghitung ulang tanda tangan dengan secret milik access key di URL. Jika cocok, URL belum kedaluwarsa dan penanda tangan diizinkan melakukan operasi tersebut, permintaan akan diproses.

URL membawa izin dari siapa pun yang menandatanganinya. AWS menjelaskan hal ini secara eksplisit: jika pengguna IAM atau role yang membuat URL tidak dapat membaca objek, URL mengembalikan 403 betapapun valid tanda tangannya.

Arti parameter X-Amz

Presigned URL SigV4 terlihat seperti ini (dengan tambahan pemisah baris):

https://my-bucket.s3.eu-west-1.amazonaws.com/reports/q3.pdf
  ?X-Amz-Algorithm=AWS4-HMAC-SHA256
  &X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20261017%2Feu-west-1%2Fs3%2Faws4_request
  &X-Amz-Date=20261017T093000Z
  &X-Amz-Expires=3600
  &X-Amz-SignedHeaders=host
  &X-Amz-Signature=5f2c...e91a
ParameterArti
X-Amz-AlgorithmAlgoritma penandatanganan: AWS4-HMAC-SHA256 untuk SigV4
X-Amz-CredentialID access key ditambah cakupan: <key-id>/<YYYYMMDD>/<region>/s3/aws4_request
X-Amz-DateWaktu URL ditandatangani, dalam UTC, yyyyMMddTHHmmssZ
X-Amz-ExpiresBerapa detik URL berlaku setelah X-Amz-Date, dari 1 hingga 604800
X-Amz-SignedHeadersHeader yang dicakup tanda tangan, selalu setidaknya host
X-Amz-SignatureTanda tangan, 64 karakter heksadesimal
X-Amz-Security-TokenHanya ada jika URL ditandatangani dengan kredensial sementara (STS, role, EC2, ECS, SSO)

Ubah bagian mana pun yang ditandatangani (key, metode, masa berlaku atau header yang ditandatangani) dan tanda tangan tidak lagi cocok. Perhatikan juga apa yang terungkap dalam teks biasa di URL: nama bucket, key objek lengkap dan ID access key Anda. Secret key tidak pernah ada di URL.

Berapa lama presigned URL bertahan

Batasnya bergantung pada kredensial yang menandatanganinya:

Ditandatangani denganMasa berlaku maksimum
Access key pengguna IAM (SigV4)7 hari, karena signing key SigV4 itu sendiri berlaku selama 7 hari
Sesi role IAM (STS AssumeRole)Hingga sesi berakhir, 1 jam secara default
Instance profile EC2Hingga kredensial role dirotasi, paling lama sekitar 6 jam
Task role ECSHingga kredensial task dirotasi, biasanya setiap 1 hingga 6 jam
Kredensial apa pun yang dicabut/dihapusLangsung berhenti, apa pun nilai X-Amz-Expires
Konsol S3Anda memilih antara 1 menit dan 12 jam

Ini menjelaskan kejutan yang paling umum: Anda meminta 7 hari dari fungsi Lambda atau instance EC2 dan tautan mati setelah satu jam atau beberapa jam. URL hanya bertahan selama kredensial di belakangnya. Jika Anda memerlukan tautan yang panjang, tandatangani dengan pengguna IAM khusus yang hanya memiliki akses baca ke bucket tersebut.

S3 memeriksa masa berlaku saat permintaan dimulai. Unduhan besar yang dimulai satu detik sebelum tenggat selesai dengan normal, tetapi percobaan ulang setelah tenggat gagal dengan AccessDenied dan pesan “Request has expired”. Meminta lebih dari 604.800 detik langsung ditolak.

Cara membuat presigned URL

AWS CLI

aws s3 presign s3://my-bucket/reports/q3.pdf --expires-in 3600

Perintah ini menandatangani URL unduhan (GET). Default-nya 3.600 detik dan maksimumnya 604.800. Versi CLI terbaru selalu menggunakan SigV4, jadi pastikan region sudah dikonfigurasi. Untuk URL unggahan, Anda memerlukan SDK.

Python (boto3)

import boto3
from botocore.config import Config

s3 = boto3.client('s3', region_name='eu-west-1', config=Config(signature_version='s3v4'))

url = s3.generate_presigned_url(
    ClientMethod='get_object',
    Params={
        'Bucket': 'my-bucket',
        'Key': 'reports/q3.pdf',
        'ResponseContentDisposition': 'attachment; filename="q3.pdf"',
    },
    ExpiresIn=3600,
)

Atur signature_version='s3v4' secara eksplisit. Referensi boto3 memperingatkan bahwa, demi kompatibilitas mundur, boto3 dapat menandatangani dengan Signature Version 2 yang lebih lama di region yang masih menerimanya, yang diam-diam membuang beberapa parameter dan header seperti Range. ResponseContentDisposition bersifat opsional: membuat browser menyimpan file dengan nama yang rapi alih-alih membukanya langsung.

JavaScript (AWS SDK v3)

import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'

const client = new S3Client({ region: 'eu-west-1' })

const url = await getSignedUrl(
  client,
  new GetObjectCommand({ Bucket: 'my-bucket', Key: 'reports/q3.pdf' }),
  { expiresIn: 3600 }
)

Jika Anda tidak menyertakan expiresIn, presigner JavaScript menggunakan 900 detik (15 menit).

Presigned URL untuk unggahan (PUT)

Ide yang sama berlaku ke arah sebaliknya. Anda menandatangani PutObject untuk satu key dan siapa pun yang memiliki URL dapat menulis objek tersebut. File berpindah langsung dari perangkat mereka ke bucket dan server Anda tidak pernah menangani byte-nya. Jika objek dengan key tersebut sudah ada, objek itu akan diganti.

import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'

const client = new S3Client({ region: 'eu-west-1' })

const url = await getSignedUrl(
  client,
  new PutObjectCommand({
    Bucket: 'my-bucket',
    Key: 'incoming/brief.pdf',
    ContentType: 'application/pdf',
  }),
  { expiresIn: 900, signableHeaders: new Set(['content-type']) }
)

await fetch(url, {
  method: 'PUT',
  headers: { 'Content-Type': 'application/pdf' },
  body: file,
})

Menambahkan content-type ke signableHeaders mengikat URL ke jenis tersebut, sehingga unggahan dengan Content-Type yang berbeda akan ditolak. Di boto3, padanannya adalah generate_presigned_url('put_object', Params={'Bucket': ..., 'Key': ..., 'ContentType': 'application/pdf'}), dan klien harus mengirim header yang sama.

Tiga hal yang perlu diperiksa sebelum mengunggah dari browser:

  • CORS. Bucket memerlukan aturan CORS yang mengizinkan origin Anda dan metode PUT. Untuk unggahan multipart, aturan tersebut juga harus mengekspos header ETag, karena browser harus membacanya dari setiap bagian.
  • Key tetap. Buat key unik di server (misalnya dengan prefix UUID) agar pengunjung tidak dapat menimpa file milik orang lain.
  • Checksum. SDK AWS saat ini menambahkan checksum CRC ke unggahan secara default. Jika unggahan presigned gagal pada provider kompatibel S3 dengan error tanda tangan atau checksum, atur requestChecksumCalculation: 'WHEN_REQUIRED' pada klien.

Presigned POST adalah mekanisme terpisah untuk formulir HTML biasa, dengan kebijakan yang dapat membatasi ukuran dan jenis konten. Tidak semua provider kompatibel S3 mendukungnya (R2 tidak), sehingga presigned PUT adalah pilihan yang lebih portabel.

File besar: unggahan multipart presigned

Satu PUT ke S3 dibatasi 5 GB, dan AWS menyarankan multipart mulai sekitar 100 MB. Multipart membagi file menjadi hingga 10.000 bagian, masing-masing 5 MiB hingga 5 GiB kecuali bagian terakhir, yang diunggah secara independen, paralel dan dengan percobaan ulang per bagian. Presigning bekerja per bagian: server memulai unggahan, menandatangani satu URL UploadPart per bagian, browser mengirim setiap potongan dan melaporkan kembali ETag-nya, lalu server menyelesaikan unggahan.

import {
  CreateMultipartUploadCommand,
  UploadPartCommand,
  CompleteMultipartUploadCommand,
} from '@aws-sdk/client-s3'

const { UploadId } = await client.send(
  new CreateMultipartUploadCommand({ Bucket: 'my-bucket', Key: 'video/raw.mov' })
)

const partUrl = await getSignedUrl(
  client,
  new UploadPartCommand({ Bucket: 'my-bucket', Key: 'video/raw.mov', UploadId, PartNumber: 1 }),
  { expiresIn: 3600 }
)

await client.send(
  new CompleteMultipartUploadCommand({
    Bucket: 'my-bucket',
    Key: 'video/raw.mov',
    UploadId,
    MultipartUpload: { Parts: [{ PartNumber: 1, ETag: etagFromPartResponse }] },
  })
)

Tambahkan aturan lifecycle yang membatalkan unggahan multipart yang tidak selesai setelah beberapa hari, atau bagian yang terbengkalai akan terus memakan penyimpanan yang ditagih.

Presigned URL di R2, B2, Spaces dan Wasabi

Provider yang menerapkan API S3 dengan SigV4 menerima kode yang sama: Anda hanya mengubah endpoint, region dan key. Detailnya berbeda, jadi periksa dokumentasi provider:

  • Cloudflare R2 mendukung presigned GET, HEAD, PUT dan DELETE, dengan masa berlaku 1 detik hingga 7 hari. R2 tidak mendukung presigned POST, dan presigned URL hanya berfungsi di domain API S3 (<ACCOUNT_ID>.r2.cloudflarestorage.com), bukan di domain kustom. Gunakan region: 'auto'.
  • Backblaze B2 menyatakan bahwa API kompatibel S3-nya mendukung presigned URL yang dibuat dengan AWS CLI atau SDK.
  • DigitalOcean Spaces dan Wasabi berfungsi dengan panggilan SDK yang sama yang diarahkan ke endpoint mereka.

Untuk harga di setiap provider, lihat perbandingan S3, R2, Spaces, Wasabi dan B2.

Error presigned URL yang umum dan cara mengatasinya

ErrorPenyebab yang biasaSolusi
SignatureDoesNotMatchMetode, header atau query berbeda dari yang ditandatangani; jam tidak sinkronKirim Content-Type dan header yang sama; sinkronkan jam dengan NTP
AccessDenied “Request has expired”URL sudah melewati X-Amz-Date + X-Amz-ExpiresBuat URL baru; perpendek jeda antara penandatanganan dan penggunaan
URL kedaluwarsa lebih cepat dari yang dimintaDitandatangani dengan kredensial sementara (role, EC2, ECS, Lambda)Tandatangani dengan kredensial yang bertahan selama tautan diperlukan
ExpiredTokenSesi STS di belakang X-Amz-Security-Token telah berakhirPerbarui kredensial sebelum menandatangani
403 AccessDenied pada URL baruPenanda tangan tidak memiliki s3:GetObject atau s3:PutObject, atau kebijakan menolaknyaBerikan izin ke principal penanda tangan; periksa kebijakan bucket
AuthorizationQueryParametersErrorMasa berlaku di atas 604.800 detik atau cakupan kredensial yang salah formatPertahankan X-Amz-Expires 7 hari atau kurang; tandatangani di region bucket
Browser diblokir oleh CORSTidak ada aturan CORS untuk origin dan metode Anda di bucketTambahkan aturan CORS dengan origin Anda, GET/PUT dan ETag yang diekspos
AccessDenied dengan HeadersNotSignedRange ditandatangani tetapi If-Range dikirim tanpa tanda tanganTambahkan If-Range ke header yang ditandatangani

Proxy perusahaan yang menulis ulang header atau query string juga merusak tanda tangan. Jika sebuah URL berfungsi dari satu jaringan dan tidak dari jaringan lain, uji tanpa proxy.

Praktik keamanan terbaik

AWS menyebut presigned URL sebagai bearer token dan merekomendasikan untuk melindunginya. Dalam praktiknya:

  • Buat masa berlakunya singkat. Hitungan menit untuk unggahan dan file sensitif, hitungan jam untuk unduhan biasa. Buat yang baru saat seseorang memerlukan file itu lagi.
  • Tandatangani dengan identitas yang sempit. Pengguna IAM atau role khusus yang hanya dapat membaca (atau hanya menulis) prefix yang dimaksud membatasi kerusakan jika tautan bocor.
  • Tambahkan pengaman di kebijakan bucket. Kondisi s3:signatureAge menolak tanda tangan yang lebih tua dari usia tertentu, dan aws:SourceIp membatasi jaringan mana yang dapat menggunakannya.
  • Jangan mencatatnya di log. Presigned URL lengkap di log aplikasi, analitik atau riwayat obrolan adalah kredensial yang berfungsi hingga kedaluwarsa.
  • Rencanakan untuk apa yang tidak dimilikinya. Tidak ada kata sandi, tidak ada hitungan unduhan dan tidak ada pencabutan per tautan, jadi tempatkan aplikasi di depannya jika Anda memerlukan hal-hal tersebut.

Untuk sisi berbagi secara mendalam, dengan opsi yang menambahkan kontrol tersebut, lihat cara berbagi file S3 tanpa menjadikan bucket publik.

Cara Nubbo menggunakan presigned URL

Nubbo dibangun di atas pola ini. Saat Anda mengunggah di explorer, server menandatangani PUT (atau, mulai 100 MB, unggahan multipart dengan tiga bagian secara paralel) dan browser Anda mengirim byte langsung ke bucket Anda. Unduhan satu file menggunakan presigned URL GET yang berlaku selama satu jam. Access key Anda disimpan terenkripsi dengan AES-256-GCM dan hanya digunakan di server untuk menandatangani.

Tautan berbagi menambahkan apa yang tidak dimiliki presigned URL mentah: kata sandi, tanggal kedaluwarsa dan batas unduhan opsional yang diperiksa Nubbo sebelum menerbitkan URL berumur pendek, dan Anda dapat menonaktifkan tautan kapan saja. Unduhan ZIP multi-file disusun di browser Anda, yang mengunduh setiap file langsung dari bucket Anda: Nubbo tidak pernah melihat isinya. Satu pengecualian yang jujur: thumbnail ditulis ke bucket Anda sendiri di .nubbo-thumbs/. Cara kerjanya sama di Amazon S3, Cloudflare R2, DigitalOcean Spaces, Wasabi, Backblaze B2 dan endpoint kompatibel S3 publik.

Pertanyaan yang sering diajukan

Apa itu presigned URL di S3?

Ini adalah tautan HTTPS biasa ke satu objek di bucket privat dengan tanda tangan yang ditambahkan ke query string. Siapa pun yang memiliki tautan tersebut dapat melakukan satu operasi yang ditandatangani, biasanya unduhan (GET) atau unggahan (PUT), hingga tautan kedaluwarsa. Bucket tetap privat dan orang yang menggunakan tautan tidak memerlukan kredensial AWS.

Berapa masa berlaku maksimum presigned URL S3?

Tujuh hari (604.800 detik) saat Anda menandatangani dengan Signature Version 4 dan key pengguna IAM jangka panjang. URL yang ditandatangani dengan kredensial sementara, seperti role yang di-assume atau instance profile EC2, berhenti berfungsi saat kredensial tersebut kedaluwarsa, meskipun Anda meminta lebih lama. Di konsol S3, Anda dapat memilih antara 1 menit dan 12 jam.

Apa arti X-Amz-Algorithm, X-Amz-Credential, X-Amz-Date, X-Amz-Expires, X-Amz-SignedHeaders dan X-Amz-Signature?

Itu adalah parameter autentikasi SigV4. Algorithm adalah metode penandatanganan (AWS4-HMAC-SHA256), Credential adalah ID access key Anda ditambah cakupan tanggal, region dan layanan, Date adalah waktu URL ditandatangani, Expires adalah berapa detik URL tetap berlaku, SignedHeaders mencantumkan header yang dicakup tanda tangan dan Signature adalah tanda tangan itu sendiri. X-Amz-Security-Token hanya muncul jika URL ditandatangani dengan kredensial sementara.

Bisakah saya mencabut presigned URL S3 sebelum kedaluwarsa?

Tidak satu per satu. Presigned URL berhenti berfungsi lebih awal hanya jika kredensial yang menandatanganinya dicabut, dihapus atau dinonaktifkan, atau jika kebijakan bucket menolak permintaan tersebut. Jika Anda perlu membatalkan tautan secara individual, tempatkan aplikasi di depannya yang hanya memberikan URL berumur pendek setelah pemeriksaannya sendiri.

Apakah presigned URL S3 aman?

Tanda tangannya tidak dapat dipalsukan atau diubah, dan bucket tetap privat. Namun, AWS menggambarkan presigned URL sebagai bearer token: siapa pun yang mendapatkan tautan dapat menggunakannya, sesering yang mereka mau, hingga kedaluwarsa. Pertahankan masa berlaku yang singkat, gunakan HTTPS dan hindari memasang tautan di tempat yang dapat disalin.

Apakah presigned URL berfungsi dengan Cloudflare R2, Backblaze B2 atau Wasabi?

Provider yang menerapkan API S3 dengan Signature Version 4 umumnya mendukungnya, dan Anda menggunakan panggilan SDK yang sama dengan endpoint provider. Cloudflare R2, misalnya, mendukung presigned GET, HEAD, PUT dan DELETE dengan masa berlaku 1 detik hingga 7 hari, tetapi tidak mendukung unggahan formulir POST maupun domain kustom.

Mengapa presigned URL saya mengembalikan SignatureDoesNotMatch?

AWS mencantumkan tiga penyebab umum: jam komputer yang tidak sinkron, proxy yang mengubah header atau query string, dan permintaan yang metode, header atau parameternya berbeda dari yang ditandatangani. Pada unggahan, penyebab yang biasa adalah mengirim Content-Type yang berbeda dari yang digunakan saat URL dibuat.

Sumber

Harga dan batas berasal dari halaman resmi di bawah ini. Provider dapat mengubahnya, jadi periksa sebelum Anda memutuskan.