Artikkel

Forhåndssignerte URL-er i S3: hva de er, hvordan de fungerer, utløpsgrenser og kodeeksempler

Hva en forhåndssignert S3-URL er, hva hver X-Amz-parameter betyr, utløpsgrensen på 7 dager, kode for opp- og nedlasting (CLI, boto3, JS) og vanlige feil.

En forhåndssignert S3-URL er en midlertidig lenke til ett objekt i en privat bucket. Den har en signatur i spørrestrengen, så den som har den, kan laste ned (eller laste opp) det objektet uten AWS-legitimasjon til lenken utløper, og bucketen blir aldri offentlig. Du lager den med dine egne nøkler, i koden din eller fra AWS CLI, og den kan vare fra 1 sekund opptil 7 dager. Denne veiledningen viser hvordan den fungerer, hva hver X-Amz-*-parameter betyr, hvor lenge den kan vare, kode for nedlastinger og opplastinger og feilene du mest sannsynlig støter på. Grensene er hentet fra dokumentasjonen til AWS og Cloudflare per oktober 2026.

Forhåndssignerte S3-URL-er i korte trekk

SpørsmålSvar
Hva gir den tilgang til?Én operasjon (GET, PUT, HEAD, DELETE…) på ett objekt
Lengste utløpstid7 dager (604 800 sekunder) med SigV4 og nøkler for en IAM-bruker
Utløp med midlertidige nøklerSlutter når rolleøkten eller STS-legitimasjonen slutter, avhengig av hva som skjer først
Område i S3-konsollen1 minutt til 12 timer
Standard utløpstid3 600 s i AWS CLI og boto3, 900 s i presigneren for JavaScript v3
Kan den brukes flere ganger?Ja, så ofte noen vil til den utløper
Kan én URL trekkes tilbake?Nei, bare ved å trekke tilbake legitimasjonen som signerte, eller avvise den i en policy
Kaller det S3 å lage en?Nei, signaturen beregnes lokalt

Slik fungerer en forhåndssignert URL

  1. Koden din (eller CLI-et) tar bucketen, objektnøkkelen, HTTP-metoden og en utløpstid.
  2. SDK-et signerer disse verdiene med den hemmelige tilgangsnøkkelen din ved hjelp av AWS Signature Version 4. Ingenting sendes til S3 på dette tidspunktet.
  3. Du gir den ferdige URL-en til noen: en nettleser, en kollega, en mobilapp.
  4. Når de bruker den, beregner S3 signaturen på nytt med hemmeligheten som hører til tilgangsnøkkelen i URL-en. Hvis den stemmer, URL-en ikke har utløpt og den som signerte har lov til å utføre operasjonen, går forespørselen gjennom.

URL-en har tillatelsene til den som signerte den. AWS er tydelig på dette: hvis IAM-brukeren eller rollen som laget URL-en ikke kan lese objektet, returnerer URL-en 403 uansett hvor gyldig signaturen er.

Hva X-Amz-parameterne betyr

En forhåndssignert URL med SigV4 ser slik ut (med linjeskift lagt til):

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
ParameterBetydning
X-Amz-AlgorithmSigneringsalgoritmen: AWS4-HMAC-SHA256 for SigV4
X-Amz-CredentialTilgangsnøkkel-ID pluss omfang: <key-id>/<YYYYMMDD>/<region>/s3/aws4_request
X-Amz-DateNår URL-en ble signert, i UTC, yyyyMMddTHHmmssZ
X-Amz-ExpiresHvor mange sekunder URL-en er gyldig etter X-Amz-Date, fra 1 til 604800
X-Amz-SignedHeadersHeaderne som signaturen dekker, alltid minst host
X-Amz-SignatureSignaturen, 64 heksadesimale tegn
X-Amz-Security-TokenFinnes bare når URL-en ble signert med midlertidig legitimasjon (STS, roller, EC2, ECS, SSO)

Endrer du en signert del (nøkkelen, metoden, utløpstiden eller en signert header), stemmer ikke signaturen lenger. Merk også hva URL-en avslører i klartekst: navnet på bucketen, hele objektnøkkelen og tilgangsnøkkel-ID-en din. Den hemmelige nøkkelen står aldri i URL-en.

Hvor lenge en forhåndssignert URL varer

Grensen avhenger av legitimasjonen som signerer den:

Signert medLengste gyldighet
Tilgangsnøkler for IAM-bruker (SigV4)7 dager, fordi selve signeringsnøkkelen i SigV4 er gyldig i 7 dager
IAM-rolleøkt (STS AssumeRole)Til økten slutter, 1 time som standard
EC2-instansprofilTil rollelegitimasjonen roteres, høyst rundt 6 timer
ECS-oppgaverolleTil oppgavelegitimasjonen roteres, vanligvis hver 1. til 6. time
Legitimasjon som trekkes tilbake eller slettesSlutter umiddelbart, uansett hva X-Amz-Expires sier
S3-konsollenDu velger mellom 1 minutt og 12 timer

Dette forklarer den vanligste overraskelsen: du ber om 7 dager fra en Lambda-funksjon eller en EC2-instans, og lenken dør etter en time eller noen få timer. URL-en lever bare så lenge som legitimasjonen bak den. Hvis du trenger lange lenker, signerer du med en egen IAM-bruker som bare har lesetilgang til den bucketen.

S3 sjekker utløpstiden når en forespørsel starter. En stor nedlasting som begynner ett sekund før fristen, fullføres normalt, men et nytt forsøk etter fristen mislykkes med AccessDenied og meldingen «Request has expired». Ber du om mer enn 604 800 sekunder, avvises det med en gang.

Slik lager du en forhåndssignert URL

AWS CLI

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

Kommandoen signerer en URL for nedlasting (GET). Standard er 3 600 sekunder og maksimum 604 800. Nyere CLI-versjoner bruker alltid SigV4, så sørg for at en region er konfigurert. For opplastings-URL-er trenger du et 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,
)

Sett signature_version='s3v4' eksplisitt. Boto3-referansen advarer om at den ellers, av hensyn til bakoverkompatibilitet, kan signere med den eldre Signature Version 2 i regioner som fortsatt godtar den, noe som stille fjerner enkelte parametere og headere, som Range. ResponseContentDisposition er valgfri: den får nettleseren til å lagre filen med et ryddig navn i stedet for å åpne den direkte.

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

Hvis du utelater expiresIn, bruker presigneren for JavaScript 900 sekunder (15 minutter).

Forhåndssignerte URL-er for opplasting (PUT)

Den samme ideen fungerer den andre veien. Du signerer en PutObject for én nøkkel, og den som har URL-en, kan skrive det objektet. Filen går rett fra enheten deres til bucketen, og serveren din håndterer aldri bytene. Hvis det allerede finnes et objekt med den nøkkelen, erstattes det.

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

Når du legger til content-type i signableHeaders, bindes URL-en til den typen, så en opplasting med en annen Content-Type avvises. I boto3 tilsvarer det generate_presigned_url('put_object', Params={'Bucket': ..., 'Key': ..., 'ContentType': 'application/pdf'}), og klienten må sende den samme headeren.

Tre ting du bør sjekke før du laster opp fra en nettleser:

  • CORS. Bucketen trenger en CORS-regel som tillater opprinnelsen din og metoden PUT. For multipart-opplastinger må den også eksponere headeren ETag, fordi nettleseren må lese den fra hver del.
  • Fast nøkkel. Lag en unik nøkkel på serveren (for eksempel med et UUID-prefiks), slik at en besøkende ikke kan overskrive filen til noen andre.
  • Sjekksummer. Nåværende AWS SDK-er legger som standard til en CRC-sjekksum på opplastinger. Hvis forhåndssignerte opplastinger mislykkes mot en S3-kompatibel leverandør med signatur- eller sjekksumfeil, setter du requestChecksumCalculation: 'WHEN_REQUIRED' på klienten.

Presigned POST er en egen mekanisme for vanlige HTML-skjemaer, med en policy som kan begrense størrelse og innholdstype. Ikke alle S3-kompatible leverandører støtter det (R2 gjør det ikke), så forhåndssignert PUT er det mest portable valget.

Store filer: forhåndssignerte multipart-opplastinger

En enkelt PUT til S3 er begrenset til 5 GB, og AWS foreslår multipart fra rundt 100 MB. Multipart deler filen i opptil 10 000 deler, hver fra 5 MiB til 5 GiB unntatt den siste, som lastes opp uavhengig, parallelt og med nye forsøk per del. Forhåndssignering skjer per del: serveren starter opplastingen, signerer én UploadPart-URL per del, nettleseren sender hver bit og rapporterer tilbake ETag, og serveren fullfører opplastingen.

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

Legg til en livssyklusregel som avbryter ufullførte multipart-opplastinger etter noen dager, ellers fortsetter forlatte deler å ta opp fakturerbar lagring.

Forhåndssignerte URL-er hos R2, B2, Spaces og Wasabi

Leverandører som implementerer S3 API-et med SigV4, godtar den samme koden: du endrer bare endepunktet, regionen og nøklene. Detaljene varierer, så sjekk dokumentasjonen til leverandøren:

  • Cloudflare R2 støtter forhåndssignerte GET, HEAD, PUT og DELETE, med en utløpstid fra 1 sekund til 7 dager. Den støtter ikke forhåndssignert POST, og forhåndssignerte URL-er fungerer bare på domenet til S3 API-et (<ACCOUNT_ID>.r2.cloudflarestorage.com), ikke på egne domener. Bruk region: 'auto'.
  • Backblaze B2 sier at det S3-kompatible API-et støtter forhåndssignerte URL-er laget med AWS CLI eller SDK-er.
  • DigitalOcean Spaces og Wasabi fungerer med de samme SDK-kallene pekt mot endepunktene deres.

For priser hos hver leverandør, se sammenligningen av S3, R2, Spaces, Wasabi og B2.

Vanlige feil med forhåndssignerte URL-er og hvordan du løser dem

FeilVanlig årsakLøsning
SignatureDoesNotMatchMetode, headere eller spørring er forskjellig fra det som ble signert; klokken går feilSend samme Content-Type og headere; synkroniser klokken med NTP
AccessDenied «Request has expired»URL-en er forbi X-Amz-Date + X-Amz-ExpiresLag en ny URL; kort ned tiden mellom signering og bruk
URL-en utløper før forventetSignert med midlertidig legitimasjon (rolle, EC2, ECS, Lambda)Signer med legitimasjon som lever like lenge som lenken må
ExpiredTokenSTS-økten bak X-Amz-Security-Token er avsluttetForny legitimasjonen før du signerer
403 AccessDenied på en ny URLDen som signerer, mangler s3:GetObject eller s3:PutObject, eller en policy avviser detGi tillatelsen til den som signerer; sjekk bucket policyer
AuthorizationQueryParametersErrorUtløpstid over 604 800 sekunder eller et feilformatert omfang i legitimasjonenHold X-Amz-Expires på 7 dager eller mindre; signer i regionen til bucketen
Nettleseren blokkeres av CORSIngen CORS-regel for opprinnelsen og metoden din på bucketenLegg til en CORS-regel med opprinnelsen din, GET/PUT og eksponert ETag
AccessDenied med HeadersNotSignedRange ble signert, men If-Range ble sendt usignertLegg til If-Range i de signerte headerne

Bedriftsproxyer som skriver om headere eller spørrestrenger, ødelegger også signaturer. Hvis en URL fungerer fra ett nettverk og ikke fra et annet, kan du teste uten proxyen.

God praksis for sikkerhet

AWS kaller forhåndssignerte URL-er bærertokener og anbefaler å beskytte dem. I praksis:

  • Hold dem korte. Minutter for opplastinger og sensitive filer, timer for vanlige nedlastinger. Lag en ny når noen trenger filen igjen.
  • Signer med en smal identitet. En egen IAM-bruker eller rolle som bare kan lese (eller bare skrive) det aktuelle prefikset, begrenser skaden hvis en lenke lekker.
  • Legg inn sikringer i bucket policyen. Betingelsen s3:signatureAge avviser signaturer som er eldre enn en angitt alder, og aws:SourceIp begrenser hvilke nettverk som kan bruke dem.
  • Ikke logg dem. Fullstendige forhåndssignerte URL-er i applikasjonslogger, analyseverktøy eller chathistorikk er fungerende legitimasjon til de utløper.
  • Planlegg for det de mangler. Det finnes ikke passord, nedlastingsteller eller tilbaketrekking per lenke, så sett en applikasjon foran når du trenger det.

For delingssiden i dybden, med alternativer som legger til disse kontrollene, se slik deler du S3-filer uten å gjøre bucketen offentlig.

Slik bruker Nubbo forhåndssignerte URL-er

Nubbo er bygd på dette mønsteret. Når du laster opp i utforskeren, signerer serveren en PUT (eller, fra 100 MB, en multipart-opplasting med tre deler parallelt), og nettleseren din sender bytene direkte til bucketen din. Nedlastinger av enkeltfiler bruker forhåndssignerte GET-URL-er som er gyldige i én time. Tilgangsnøklene dine lagres kryptert med AES-256-GCM og brukes bare på serveren til å signere.

Delingslenker legger til det rå forhåndssignerte URL-er mangler: valgfritt passord, utløpsdato og nedlastingsgrense som Nubbo sjekker før den utsteder en kortlivet URL, og du kan deaktivere en lenke når som helst. ZIP-nedlastinger med flere filer settes sammen i nettleseren din, som laster ned hver fil rett fra bucketen din: Nubbo ser aldri innholdet. Ett ærlig unntak: miniatyrbilder skrives til din egen bucket under .nubbo-thumbs/. Det fungerer på samme måte med Amazon S3, Cloudflare R2, DigitalOcean Spaces, Wasabi, Backblaze B2 og offentlige S3-kompatible endepunkter.

Ofte stilte spørsmål

Hva er en forhåndssignert URL i S3?

Det er en vanlig HTTPS-lenke til ett objekt i en privat bucket, med en signatur lagt til i spørrestrengen. Den som har lenken, kan utføre den ene operasjonen den ble signert for, vanligvis en nedlasting (GET) eller en opplasting (PUT), til den utløper. Bucketen forblir privat, og den som bruker lenken, trenger ingen AWS-legitimasjon.

Hva er lengste utløpstid for en forhåndssignert S3-URL?

Sju dager (604 800 sekunder) når du signerer med Signature Version 4 og langvarige nøkler for en IAM-bruker. En URL som er signert med midlertidig legitimasjon, for eksempel en antatt rolle eller en EC2-instansprofil, slutter å virke når den legitimasjonen utløper, selv om du ba om lengre tid. I S3-konsollen kan du velge mellom 1 minutt og 12 timer.

Hva betyr X-Amz-Algorithm, X-Amz-Credential, X-Amz-Date, X-Amz-Expires, X-Amz-SignedHeaders og X-Amz-Signature?

De er autentiseringsparameterne i SigV4. Algorithm er signeringsmetoden (AWS4-HMAC-SHA256), Credential er tilgangsnøkkel-ID-en din pluss omfanget med dato, region og tjeneste, Date er når URL-en ble signert, Expires er hvor mange sekunder den er gyldig, SignedHeaders lister headerne som signaturen dekker, og Signature er selve signaturen. X-Amz-Security-Token vises bare når URL-en ble signert med midlertidig legitimasjon.

Kan jeg trekke tilbake en forhåndssignert S3-URL før den utløper?

Ikke én og én. En forhåndssignert URL slutter å virke før tiden bare når legitimasjonen som signerte den, trekkes tilbake, slettes eller deaktiveres, eller når en bucket policy avviser forespørselen. Hvis du må kunne annullere enkeltlenker, setter du en applikasjon foran som bare deler ut kortlivede URL-er etter sine egne kontroller.

Er forhåndssignerte S3-URL-er sikre?

Signaturen kan ikke forfalskes eller endres, og bucketen forblir privat. Men AWS beskriver forhåndssignerte URL-er som bærertokener (bearer tokens): alle som får lenken, kan bruke den, så mange ganger de vil, til den utløper. Hold utløpstidene korte, bruk HTTPS og unngå å legge ut lenkene der de kan kopieres.

Fungerer forhåndssignerte URL-er med Cloudflare R2, Backblaze B2 eller Wasabi?

Leverandører som implementerer S3 API-et med Signature Version 4, støtter dem som regel, og du bruker de samme SDK-kallene med endepunktet til leverandøren. Cloudflare R2 støtter for eksempel forhåndssignerte GET, HEAD, PUT og DELETE med en utløpstid fra 1 sekund til 7 dager, men ikke opplasting via POST-skjema og ikke egne domener.

Hvorfor gir den forhåndssignerte URL-en min SignatureDoesNotMatch?

AWS oppgir tre vanlige årsaker: en datamaskinklokke som går feil, en proxy som endrer headere eller spørrestrengen, og en forespørsel der metoden, headerne eller parameterne er forskjellige fra dem som ble signert. Ved opplastinger er den vanlige synderen at det sendes en annen Content-Type enn den som ble brukt da URL-en ble laget.

Kilder

Priser og grenser er hentet fra de offisielle sidene nedenfor. Leverandørene endrer dem, så sjekk før du bestemmer deg.