Článek

Presigned URL v S3: co to je, jak fungují, limity platnosti a ukázky kódu

Co je presigned URL v S3, co znamená každý parametr X-Amz, limit platnosti 7 dní, kód pro nahrávání a stahování (CLI, boto3, JS) a řešení častých chyb.

Presigned URL v S3 je dočasný odkaz na jeden objekt v soukromém bucketu. V query stringu nese podpis, takže kdo ji má, může daný objekt stáhnout (nebo nahrát) bez přihlašovacích údajů AWS, dokud odkaz nevyprší, a bucket se nikdy nestane veřejným. Vytvoříte ji svými vlastními klíči, ve svém kódu nebo z AWS CLI, a může platit od 1 sekundy do 7 dní. Tento návod vysvětluje, jak funguje, co znamená každý parametr X-Amz-*, jak dlouho může platit, kód pro stahování a nahrávání a chyby, na které nejspíš narazíte. Limity vycházejí z dokumentace AWS a Cloudflare k říjnu 2026.

Presigned URL v S3 v kostce

OtázkaOdpověď
Co umožňuje?Jednu operaci (GET, PUT, HEAD, DELETE…) na jednom objektu
Maximální platnost7 dní (604 800 sekund) se SigV4 a klíči uživatele IAM
Platnost s dočasnými klíčiKončí s koncem relace role nebo údajů STS, podle toho, co nastane dřív
Rozsah v konzoli S31 minuta až 12 hodin
Výchozí platnost3 600 s v AWS CLI a boto3, 900 s v presigneru JavaScript v3
Lze ji použít víckrát?Ano, kolikrát kdo chce, dokud nevyprší
Lze jednu URL zneplatnit?Ne, jen odvoláním podepisujících údajů nebo zamítnutím v zásadě
Volá její vytvoření S3?Ne, podpis se počítá lokálně

Jak presigned URL funguje

  1. Váš kód (nebo CLI) vezme bucket, klíč objektu, metodu HTTP a dobu platnosti.
  2. SDK tyto hodnoty podepíše vaším tajným přístupovým klíčem pomocí AWS Signature Version 4. V tuto chvíli se do S3 nic neposílá.
  3. Výslednou URL předáte někomu dalšímu: prohlížeči, kolegovi, mobilní aplikaci.
  4. Když ji použije, S3 přepočítá podpis se secretem, který patří k přístupovému klíči v URL. Pokud se shoduje, URL nevypršela a podepisující má oprávnění tuto operaci provést, požadavek projde.

URL nese oprávnění toho, kdo ji podepsal. AWS je v tom jasné: pokud uživatel IAM nebo role, která URL vygenerovala, nemůže objekt číst, URL vrátí 403, ať je podpis jakkoli platný.

Co znamenají parametry X-Amz

Presigned URL se SigV4 vypadá takto (zalomení řádků přidána):

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
ParametrVýznam
X-Amz-AlgorithmAlgoritmus podpisu: AWS4-HMAC-SHA256 pro SigV4
X-Amz-CredentialID přístupového klíče plus rozsah: <key-id>/<YYYYMMDD>/<region>/s3/aws4_request
X-Amz-DateKdy byla URL podepsána, v UTC, yyyyMMddTHHmmssZ
X-Amz-ExpiresKolik sekund je URL platná po X-Amz-Date, od 1 do 604800
X-Amz-SignedHeadersHlavičky pokryté podpisem, vždy alespoň host
X-Amz-SignaturePodpis, 64 hexadecimálních znaků
X-Amz-Security-TokenJen pokud byla URL podepsána dočasnými přihlašovacími údaji (STS, role, EC2, ECS, SSO)

Změňte jakoukoli podepsanou část (klíč, metodu, platnost nebo podepsanou hlavičku) a podpis přestane sedět. Všimněte si také, co URL prozrazuje v čitelné podobě: název bucketu, celý klíč objektu a ID vašeho přístupového klíče. Tajný klíč v URL nikdy není.

Jak dlouho presigned URL platí

Limit závisí na přihlašovacích údajích, které ji podepisují:

Podepsáno pomocíMaximální platnost
Přístupové klíče uživatele IAM (SigV4)7 dní, protože samotný podpisový klíč SigV4 platí 7 dní
Relace role IAM (STS AssumeRole)Do konce relace, ve výchozím stavu 1 hodina
Profil instance EC2Do rotace údajů role, nejvýše zhruba 6 hodin
Role úlohy ECSDo rotace údajů úlohy, obvykle každých 1 až 6 hodin
Jakékoli odvolané nebo smazané údajePřestane okamžitě, bez ohledu na X-Amz-Expires
Konzole S3Volíte mezi 1 minutou a 12 hodinami

To vysvětluje nejčastější překvapení: z funkce Lambda nebo instance EC2 požádáte o 7 dní a odkaz zemře po hodině nebo pár hodinách. URL žije jen tak dlouho jako přihlašovací údaje za ní. Pokud potřebujete dlouhé odkazy, podepisujte vyhrazeným uživatelem IAM, který má přístup ke čtení jen k tomuto bucketu.

S3 kontroluje platnost při zahájení požadavku. Velké stahování, které začne sekundu před termínem, normálně doběhne, ale opakovaný pokus po termínu selže s AccessDenied a zprávou „Request has expired“. Žádost o víc než 604 800 sekund je rovnou odmítnuta.

Jak vygenerovat presigned URL

AWS CLI

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

Příkaz podepíše URL pro stažení (GET). Výchozí hodnota je 3 600 sekund a maximum 604 800. Novější verze CLI vždy používají SigV4, takže mějte nastavený region. Pro URL pro nahrávání potřebujete 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,
)

Nastavte signature_version='s3v4' výslovně. Reference boto3 upozorňuje, že kvůli zpětné kompatibilitě jinak může v regionech, které ho stále přijímají, podepisovat starší Signature Version 2, která potichu zahodí některé parametry a hlavičky, například Range. ResponseContentDisposition je volitelné: prohlížeč pak soubor uloží s čistým názvem, místo aby ho otevřel přímo.

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 }
)

Pokud expiresIn vynecháte, presigner JavaScript použije 900 sekund (15 minut).

Presigned URL pro nahrávání (PUT)

Stejný princip funguje i opačným směrem. Podepíšete PutObject pro jeden klíč a kdo má URL, může tento objekt zapsat. Soubor jde přímo z jeho zařízení do bucketu a váš server se bajtů vůbec nedotkne. Pokud objekt s tímto klíčem už existuje, bude nahrazen.

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,
})

Přidání content-type do signableHeaders váže URL na tento typ, takže nahrání s jiným Content-Type bude odmítnuto. V boto3 je ekvivalentem generate_presigned_url('put_object', Params={'Bucket': ..., 'Key': ..., 'ContentType': 'application/pdf'}) a klient musí poslat stejnou hlavičku.

Tři věci, které před nahráváním z prohlížeče zkontrolovat:

  • CORS. Bucket potřebuje pravidlo CORS, které povoluje váš origin a metodu PUT. Pro nahrávání po částech musí také zpřístupnit hlavičku ETag, protože ji prohlížeč musí z každé části přečíst.
  • Pevný klíč. Klíč generujte na serveru jako jedinečný (například s prefixem UUID), aby návštěvník nemohl přepsat cizí soubor.
  • Kontrolní součty. Současné SDK od AWS ve výchozím stavu přidávají k nahrávání kontrolní součet CRC. Pokud presigned nahrávání u poskytovatele kompatibilního s S3 selhává s chybami podpisu nebo kontrolního součtu, nastavte na klientovi requestChecksumCalculation: 'WHEN_REQUIRED'.

Presigned POST je samostatný mechanismus pro obyčejné HTML formuláře, se zásadou, která může omezit velikost a typ obsahu. Ne každý poskytovatel kompatibilní s S3 ho podporuje (R2 ne), proto je presigned PUT přenositelnější volbou.

Velké soubory: presigned nahrávání po částech

Jeden PUT do S3 je omezen na 5 GB a AWS doporučuje nahrávání po částech zhruba od 100 MB. Nahrávání po částech rozdělí soubor až na 10 000 částí, každou od 5 MiB do 5 GiB kromě poslední, které se nahrávají nezávisle, paralelně a s opakováním po jednotlivých částech. Podepisování funguje po částech: server zahájí nahrávání, podepíše jednu URL UploadPart pro každou část, prohlížeč pošle každý kus a vrátí jeho ETag a server nahrávání dokončí.

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 }] },
  })
)

Přidejte pravidlo životního cyklu, které nedokončená nahrávání po částech po několika dnech zruší, jinak opuštěné části dál zabírají účtované úložiště.

Presigned URL v R2, B2, Spaces a Wasabi

Poskytovatelé, kteří implementují S3 API se SigV4, přijmou stejný kód: změníte jen endpoint, region a klíče. Podrobnosti se liší, proto si ověřte dokumentaci poskytovatele:

  • Cloudflare R2 podporuje presigned GET, HEAD, PUT a DELETE s platností od 1 sekundy do 7 dní. Nepodporuje presigned POST a presigned URL fungují jen na doméně S3 API (<ACCOUNT_ID>.r2.cloudflarestorage.com), ne na vlastních doménách. Použijte region: 'auto'.
  • Backblaze B2 uvádí, že jeho API kompatibilní s S3 podporuje presigned URL generované přes AWS CLI nebo SDK.
  • DigitalOcean Spaces a Wasabi fungují se stejnými voláními SDK nasměrovanými na jejich endpointy.

Ceny u jednotlivých poskytovatelů najdete ve srovnání S3, R2, Spaces, Wasabi a B2.

Časté chyby presigned URL a jak je opravit

ChybaObvyklá příčinaOprava
SignatureDoesNotMatchMetoda, hlavičky nebo query se liší od podepsaných; nesynchronizované hodinyPošlete stejný Content-Type a hlavičky; synchronizujte hodiny přes NTP
AccessDenied “Request has expired”URL je za X-Amz-Date + X-Amz-ExpiresVygenerujte novou URL; zkraťte dobu mezi podpisem a použitím
URL vyprší dřív, než jste požadovaliPodepsáno dočasnými údaji (role, EC2, ECS, Lambda)Podepisujte údaji, které žijí tak dlouho, jako má žít odkaz
ExpiredTokenRelace STS za X-Amz-Security-Token skončilaPřed podpisem obnovte přihlašovací údaje
403 AccessDenied u čerstvé URLPodepisující nemá s3:GetObject nebo s3:PutObject, nebo ho zamítá zásadaUdělte oprávnění podepisujícímu principálu; zkontrolujte zásady bucketu
AuthorizationQueryParametersErrorPlatnost nad 604 800 sekund nebo chybný rozsah údajůDržte X-Amz-Expires na 7 dnech nebo méně; podepisujte v regionu bucketu
Prohlížeč blokován kvůli CORSBucket nemá pravidlo CORS pro váš origin a metoduPřidejte pravidlo CORS s vaším originem, GET/PUT a zpřístupněným ETag
AccessDenied s HeadersNotSignedRange byl podepsán, ale If-Range byl odeslán nepodepsanýPřidejte If-Range do podepsaných hlaviček

Podpisy rozbíjejí i firemní proxy, které přepisují hlavičky nebo query stringy. Pokud URL funguje z jedné sítě a z jiné ne, vyzkoušejte to bez proxy.

Osvědčené postupy pro bezpečnost

AWS označuje presigned URL za bearer tokeny a doporučuje je chránit. V praxi:

  • Držte je krátké. Minuty pro nahrávání a citlivé soubory, hodiny pro běžná stahování. Když někdo soubor potřebuje znovu, vygenerujte novou.
  • Podepisujte úzce vymezenou identitou. Vyhrazený uživatel nebo role IAM, která může daný prefix jen číst (nebo jen zapisovat), omezí škody, pokud odkaz unikne.
  • Přidejte pojistky do zásady bucketu. Podmínka s3:signatureAge odmítá podpisy starší než nastavený věk a aws:SourceIp omezuje, ze kterých sítí je lze použít.
  • Nelogujte je. Celé presigned URL v aplikačních logech, analytice nebo historii chatu jsou funkční přihlašovací údaje, dokud nevyprší.
  • Počítejte s tím, co jim chybí. Nemají heslo, počítadlo stažení ani zneplatnění jednotlivých odkazů, takže když to potřebujete, postavte před bucket aplikaci.

Sdílení do hloubky, s možnostmi, které tyto kontroly přidávají, najdete v článku jak sdílet soubory S3, aniž byste bucket zveřejnili.

Jak Nubbo používá presigned URL

Nubbo je postavené právě na tomto principu. Když nahráváte v průzkumníku, server podepíše PUT (nebo, od 100 MB, nahrávání po částech se třemi částmi paralelně) a váš prohlížeč pošle bajty přímo do vašeho bucketu. Stahování jednotlivých souborů používá presigned URL GET s platností jedna hodina. Vaše přístupové klíče se ukládají zašifrované pomocí AES-256-GCM a na serveru se používají jen k podpisu.

Odkazy ke sdílení přidávají to, co holým presigned URL chybí: volitelné heslo, datum vypršení a limit stažení, které Nubbo zkontroluje dřív, než vydá krátkodobou URL, a odkaz můžete kdykoli deaktivovat. ZIP archivy s více soubory sestavuje váš prohlížeč, který stahuje každý soubor přímo z vašeho bucketu: Nubbo obsah nevidí. Jedna poctivá výjimka: náhledy se zapisují do vašeho vlastního bucketu pod .nubbo-thumbs/. Funguje to stejně v Amazon S3, Cloudflare R2, DigitalOcean Spaces, Wasabi, Backblaze B2 a na veřejných endpointech kompatibilních s S3.

Časté dotazy

Co je presigned URL v S3?

Je to běžný odkaz HTTPS na jeden objekt v soukromém bucketu s podpisem přidaným do query stringu. Kdo odkaz má, může provést jedinou operaci, pro kterou byl podepsán, obvykle stažení (GET) nebo nahrání (PUT), dokud nevyprší. Bucket zůstává soukromý a ten, kdo odkaz používá, nepotřebuje přihlašovací údaje AWS.

Jaká je maximální platnost presigned URL v S3?

Sedm dní (604 800 sekund) při podpisu přes Signature Version 4 s dlouhodobými klíči uživatele IAM. URL podepsaná dočasnými přihlašovacími údaji, například převzatou rolí nebo profilem instance EC2, přestane fungovat, když tyto údaje vyprší, i když jste žádali o delší dobu. V konzoli S3 můžete zvolit 1 minutu až 12 hodin.

Co znamenají X-Amz-Algorithm, X-Amz-Credential, X-Amz-Date, X-Amz-Expires, X-Amz-SignedHeaders a X-Amz-Signature?

Jsou to autentizační parametry SigV4. Algorithm je metoda podpisu (AWS4-HMAC-SHA256), Credential je ID vašeho přístupového klíče spolu s datem, regionem a rozsahem služby, Date je okamžik podpisu URL, Expires je počet sekund platnosti, SignedHeaders vypisuje hlavičky pokryté podpisem a Signature je samotný podpis. X-Amz-Security-Token se objeví jen tehdy, když byla URL podepsána dočasnými přihlašovacími údaji.

Mohu presigned URL v S3 zneplatnit před vypršením?

Ne jednotlivě. Presigned URL přestane fungovat dřív jen tehdy, když jsou přihlašovací údaje, které ji podepsaly, odvolány, smazány nebo deaktivovány, nebo když požadavek zamítne zásada bucketu. Pokud potřebujete rušit jednotlivé odkazy, postavte před bucket aplikaci, která vydává krátkodobé URL až po vlastních kontrolách.

Jsou presigned URL v S3 bezpečné?

Podpis nelze padělat ani změnit a bucket zůstává soukromý. AWS ale presigned URL popisuje jako bearer tokeny: kdokoli odkaz získá, může ho použít, kolikrát chce, dokud nevyprší. Držte dobu platnosti krátkou, používejte HTTPS a nezveřejňujte odkazy tam, kde je lze zkopírovat.

Fungují presigned URL s Cloudflare R2, Backblaze B2 nebo Wasabi?

Poskytovatelé, kteří implementují S3 API se Signature Version 4, je obecně podporují a používáte stejná volání SDK s endpointem poskytovatele. Cloudflare R2 například podporuje presigned GET, HEAD, PUT a DELETE s platností od 1 sekundy do 7 dní, ale ne nahrávání formulářem POST a ne vlastní domény.

Proč moje presigned URL vrací SignatureDoesNotMatch?

AWS uvádí tři časté příčiny: nesynchronizované hodiny počítače, proxy, která mění hlavičky nebo query string, a požadavek, jehož metoda, hlavičky nebo parametry se liší od podepsaných. U nahrávání bývá viníkem odeslání jiného Content-Type, než jaký byl použit při generování URL.

Zdroje

Ceny a limity pocházejí z níže uvedených oficiálních stránek. Poskytovatelé je mění, proto si je před rozhodnutím ověřte.