Статия

Presigned URL адреси в S3: какво са, как работят, срокове на валидност и примери с код

Какво е presigned URL в S3, какво значи всеки X-Amz параметър, лимитът от 7 дни, код за качване и изтегляне (CLI, boto3, JS) и решения на честите грешки.

Presigned URL в S3 е временна връзка към един обект в частен bucket. Тя носи подпис в query низа си, така че който я притежава, може да изтегли (или качи) този обект без идентификационни данни за AWS, докато връзката не изтече, а bucket-ът никога не става публичен. Създавате я със собствените си ключове, в кода си или от AWS CLI, и може да е валидна от 1 секунда до 7 дни. Това ръководство обяснява как работи, какво означава всеки параметър X-Amz-*, колко дълго може да е валидна, код за изтегляния и качвания и грешките, които най-вероятно ще срещнете. Ограниченията са взети от документацията на AWS и Cloudflare към октомври 2026.

Presigned URL адресите в S3 накратко

ВъпросОтговор
Какво позволява?Една операция (GET, PUT, HEAD, DELETE…) върху един обект
Максимален срок7 дни (604 800 секунди) със SigV4 и ключове на IAM потребител
Срок с временни ключовеИзтича, когато свърши сесията на ролята или STS данните, което настъпи първо
Диапазон в конзолата на S3От 1 минута до 12 часа
Срок по подразбиране3600 s в AWS CLI и boto3, 900 s в presigner-а на JavaScript v3
Може ли да се използва няколко пъти?Да, колкото пъти иска всеки, докато не изтече
Може ли да се отмени един URL адрес?Не, само чрез отнемане на подписващите данни или отказ в политика
Създаването му извиква ли S3?Не, подписът се изчислява локално

Как работи presigned URL

  1. Вашият код (или CLI) взема bucket-а, ключа на обекта, HTTP метода и срок на валидност.
  2. SDK подписва тези стойности с вашия secret access key чрез AWS Signature Version 4. В този момент нищо не се изпраща към S3.
  3. Давате получения URL адрес на някого: браузър, колега, мобилно приложение.
  4. Когато го използват, S3 изчислява отново подписа със secret, който принадлежи на access key в URL адреса. Ако съвпада, URL адресът не е изтекъл и подписалият има право да извърши тази операция, заявката минава.

URL адресът носи правата на този, който го е подписал. AWS е категоричен по този въпрос: ако IAM потребителят или ролята, генерирали URL адреса, не могат да четат обекта, URL адресът връща 403, колкото и валиден да е подписът.

Какво означават параметрите X-Amz

Presigned URL със SigV4 изглежда така (с добавени нови редове):

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
ПараметърЗначение
X-Amz-AlgorithmАлгоритъмът на подписване: AWS4-HMAC-SHA256 за SigV4
X-Amz-CredentialAccess key ID плюс обхват: <key-id>/<YYYYMMDD>/<region>/s3/aws4_request
X-Amz-DateКога е подписан URL адресът, в UTC, yyyyMMddTHHmmssZ
X-Amz-ExpiresКолко секунди е валиден URL адресът след X-Amz-Date, от 1 до 604800
X-Amz-SignedHeadersЗаглавките, обхванати от подписа, винаги поне host
X-Amz-SignatureПодписът, 64 шестнадесетични знака
X-Amz-Security-TokenПрисъства само когато URL адресът е подписан с временни данни (STS, роли, EC2, ECS, SSO)

Ако промените която и да е подписана част (ключа, метода, срока или подписана заглавка), подписът вече не съвпада. Обърнете внимание и какво разкрива URL адресът като обикновен текст: името на bucket-а, пълния ключ на обекта и вашия access key ID. Secret key никога не е в URL адреса.

Колко дълго е валиден presigned URL

Ограничението зависи от идентификационните данни, които го подписват:

Подписан сМаксимална валидност
Ключове за достъп на IAM потребител (SigV4)7 дни, защото самият ключ за подписване на SigV4 е валиден 7 дни
Сесия на IAM роля (STS AssumeRole)До края на сесията, по подразбиране 1 час
Профил на EC2 инстанцияДо ротацията на данните на ролята, най-много около 6 часа
Роля на ECS задачаДо ротацията на данните на задачата, обикновено на всеки 1 до 6 часа
Отнети или изтрити данниСпира веднага, каквото и да пише в X-Amz-Expires
Конзолата на S3Избирате между 1 минута и 12 часа

Това обяснява най-честата изненада: поискате 7 дни от Lambda функция или EC2 инстанция, а връзката спира да работи след час или няколко часа. URL адресът живее само толкова, колкото данните зад него. Ако ви трябват дълготрайни връзки, подписвайте със специален IAM потребител, който има достъп за четене само до този bucket.

S3 проверява срока, когато заявката започне. Голямо изтегляне, което започне секунда преди крайния срок, завършва нормално, но повторен опит след срока се проваля с AccessDenied и съобщението „Request has expired“. Искане за повече от 604 800 секунди се отхвърля направо.

Как да генерирате presigned URL

AWS CLI

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

Командата подписва URL адрес за изтегляне (GET). По подразбиране срокът е 3600 секунди, а максимумът е 604 800. Последните версии на CLI винаги използват SigV4, затова се уверете, че е конфигуриран регион. За URL адреси за качване ви трябва 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,
)

Задайте изрично signature_version='s3v4'. Справочникът на boto3 предупреждава, че заради обратна съвместимост иначе може да подпише с по-старата Signature Version 2 в регионите, които все още я приемат, което мълчаливо изпуска някои параметри и заглавки, като Range. ResponseContentDisposition е по избор: кара браузъра да запази файла с чисто име, вместо да го отвори директно.

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

Ако пропуснете expiresIn, presigner-ът на JavaScript използва 900 секунди (15 минути).

Presigned URL адреси за качване (PUT)

Същата идея работи и в обратната посока. Подписвате PutObject за един ключ и който има URL адреса, може да запише този обект. Файлът отива директно от устройството му в bucket-а и вашият сървър никога не обработва байтовете. Ако вече съществува обект с този ключ, той се заменя.

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

Добавянето на content-type към signableHeaders обвързва URL адреса с този тип, така че качване с различен Content-Type се отхвърля. В boto3 еквивалентът е generate_presigned_url('put_object', Params={'Bucket': ..., 'Key': ..., 'ContentType': 'application/pdf'}), а клиентът трябва да изпрати същата заглавка.

Три неща, които да проверите, преди да качвате от браузър:

  • CORS. Bucket-ът се нуждае от CORS правило, което разрешава вашия произход и метода PUT. За multipart качвания то трябва и да прави видима заглавката ETag, защото браузърът трябва да я прочете от всяка част.
  • Фиксиран ключ. Генерирайте уникален ключ на сървъра (например с UUID префикс), за да не може посетител да презапише чужд файл.
  • Контролни суми. Текущите AWS SDK добавят CRC контролна сума към качванията по подразбиране. Ако presigned качванията към S3-съвместим доставчик се провалят с грешки за подпис или контролна сума, задайте requestChecksumCalculation: 'WHEN_REQUIRED' в клиента.

Presigned POST е отделен механизъм за обикновени HTML формуляри, с политика, която може да ограничи размера и типа на съдържанието. Не всеки S3-съвместим доставчик го поддържа (R2 не го поддържа), затова presigned PUT е по-преносимият избор.

Големи файлове: presigned multipart качвания

Единичен PUT към S3 е ограничен до 5 GB, а AWS препоръчва multipart от около 100 MB. Multipart разделя файла на до 10 000 части, всяка от 5 MiB до 5 GiB с изключение на последната, които се качват независимо, паралелно и с повторни опити за всяка част. Подписването работи на част: сървърът стартира качването, подписва по един URL адрес UploadPart за всяка част, браузърът изпраща всяко парче и връща неговия ETag, а сървърът завършва качването.

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

Добавете правило за жизнения цикъл, което прекратява незавършените multipart качвания след няколко дни, иначе изоставените части продължават да заемат таксувано пространство.

Presigned URL адреси в R2, B2, Spaces и Wasabi

Доставчиците, които реализират S3 API със SigV4, приемат същия код: променяте само endpoint-а, региона и ключовете. Детайлите се различават, затова проверете документацията на доставчика:

  • Cloudflare R2 поддържа presigned GET, HEAD, PUT и DELETE със срок от 1 секунда до 7 дни. Не поддържа presigned POST, а presigned URL адресите работят само на домейна на S3 API (<ACCOUNT_ID>.r2.cloudflarestorage.com), не и на собствени домейни. Използвайте region: 'auto'.
  • Backblaze B2 посочва, че неговият S3-съвместим API поддържа presigned URL адреси, генерирани с AWS CLI или SDK.
  • DigitalOcean Spaces и Wasabi работят със същите извиквания на SDK, насочени към техните endpoint-и.

За цените при всеки доставчик вижте сравнението на S3, R2, Spaces, Wasabi и B2.

Чести грешки с presigned URL и как да ги поправите

ГрешкаОбичайна причинаРешение
SignatureDoesNotMatchМетодът, заглавките или query низът се различават от подписаните; несинхронизиран часовникИзпращайте същите Content-Type и заглавки; синхронизирайте часовника с NTP
AccessDenied „Request has expired“URL адресът е след X-Amz-Date + X-Amz-ExpiresГенерирайте нов URL адрес; съкратете времето между подписването и използването
URL адресът изтича по-рано от поискания срокПодписан с временни данни (роля, EC2, ECS, Lambda)Подписвайте с данни, които живеят толкова, колкото трябва да живее връзката
ExpiredTokenSTS сесията зад X-Amz-Security-Token е приключилаОпреснете данните преди подписване
403 AccessDenied при нов URL адресПодписващият няма s3:GetObject или s3:PutObject, или политика го отказваДайте правото на подписващия субект; проверете bucket policies
AuthorizationQueryParametersErrorСрок над 604 800 секунди или неправилен обхват на даннитеДръжте X-Amz-Expires до 7 дни; подписвайте в региона на bucket-а
Браузърът е блокиран от CORSНяма CORS правило за вашия произход и метод в bucket-аДобавете CORS правило с вашия произход, GET/PUT и видим ETag
AccessDenied с HeadersNotSignedRange е подписан, но If-Range е изпратен неподписанДобавете If-Range към подписаните заглавки

Корпоративните проксита, които пренаписват заглавки или query низове, също развалят подписите. Ако URL адрес работи от една мрежа, а от друга не, тествайте без проксито.

Добри практики за сигурност

AWS нарича presigned URL адресите bearer токени и препоръчва да ги защитавате. На практика:

  • Дръжте ги кратки. Минути за качвания и чувствителни файлове, часове за обикновени изтегляния. Генерирайте нов, когато някой отново има нужда от файла.
  • Подписвайте с тясна идентичност. Специален IAM потребител или роля, които могат само да четат (или само да записват) въпросния префикс, ограничават щетите, ако връзка изтече навън.
  • Добавете предпазни мерки в bucket policy. Условието s3:signatureAge отхвърля подписи, по-стари от зададена възраст, а aws:SourceIp ограничава от кои мрежи могат да се използват.
  • Не ги записвайте в логове. Пълните presigned URL адреси в логовете на приложения, в аналитиката или в историята на чатове са работещи идентификационни данни, докато не изтекат.
  • Планирайте за това, което им липсва. Няма парола, брояч на изтеглянията и отмяна на отделна връзка, затова поставете отпред приложение, когато ви трябват тези неща.

За задълбочен поглед към споделянето, с варианти, които добавят тези контроли, вижте как да споделяте S3 файлове, без да правите bucket-а публичен.

Как Nubbo използва presigned URL адреси

Nubbo е изграден върху този модел. Когато качвате във файловия мениджър, сървърът подписва PUT (или, от 100 MB нагоре, multipart качване с три паралелни части) и браузърът ви изпраща байтовете директно към вашия bucket. Изтеглянията на отделни файлове използват presigned GET URL адреси, валидни един час. Ключовете ви за достъп се съхраняват криптирани с AES-256-GCM и се използват само на сървъра за подписване.

Връзките за споделяне добавят това, което липсва на обикновените presigned URL адреси: парола, срок на валидност и лимит на изтеглянията по избор, които Nubbo проверява, преди да издаде краткотраен URL адрес, а можете да деактивирате връзка по всяко време. ZIP изтеглянията на няколко файла се сглобяват в браузъра ви, който изтегля всеки файл директно от вашия bucket: Nubbo не вижда съдържанието. Едно честно изключение: миниатюрите се записват във вашия bucket в .nubbo-thumbs/. Работи по един и същ начин с Amazon S3, Cloudflare R2, DigitalOcean Spaces, Wasabi, Backblaze B2 и публични S3-съвместими endpoint-и.

Често задавани въпроси

Какво е presigned URL в S3?

Това е обикновена HTTPS връзка към един обект в частен bucket с добавен подпис в query низа. Който има връзката, може да извърши единствената операция, за която е подписана, обикновено изтегляне (GET) или качване (PUT), докато не изтече. Bucket-ът остава частен, а човекът, който използва връзката, няма нужда от идентификационни данни за AWS.

Какъв е максималният срок на валидност на presigned URL в S3?

Седем дни (604 800 секунди), когато подписвате със Signature Version 4 и дълготрайни ключове на IAM потребител. URL адрес, подписан с временни идентификационни данни, например поета роля или профил на EC2 инстанция, спира да работи, когато тези данни изтекат, дори да сте поискали по-дълъг срок. В конзолата на S3 можете да изберете между 1 минута и 12 часа.

Какво означават X-Amz-Algorithm, X-Amz-Credential, X-Amz-Date, X-Amz-Expires, X-Amz-SignedHeaders и X-Amz-Signature?

Това са параметрите за удостоверяване на SigV4. Algorithm е методът на подписване (AWS4-HMAC-SHA256), Credential е вашият access key ID плюс обхвата от дата, регион и услуга, Date е моментът на подписване на URL адреса, Expires е колко секунди остава валиден, SignedHeaders изброява заглавките, обхванати от подписа, а Signature е самият подпис. X-Amz-Security-Token се появява само когато URL адресът е подписан с временни идентификационни данни.

Мога ли да отменя presigned URL в S3, преди да изтече?

Не поотделно. Presigned URL спира да работи по-рано само когато идентификационните данни, които са го подписали, бъдат отнети, изтрити или деактивирани, или когато bucket policy откаже заявката. Ако трябва да отменяте отделни връзки, поставете отпред приложение, което раздава краткотрайни URL адреси само след собствените си проверки.

Сигурни ли са presigned URL адресите в S3?

Подписът не може да бъде подправен или променен, а bucket-ът остава частен. Но AWS описва presigned URL адресите като bearer токени: всеки, който получи връзката, може да я използва колкото пъти иска, докато не изтече. Задавайте кратки срокове, използвайте HTTPS и не публикувайте връзките там, откъдето могат да бъдат копирани.

Работят ли presigned URL адресите с Cloudflare R2, Backblaze B2 или Wasabi?

Доставчиците, които реализират S3 API със Signature Version 4, обикновено ги поддържат, като използвате същите извиквания на SDK с endpoint-а на доставчика. Cloudflare R2 например поддържа presigned GET, HEAD, PUT и DELETE със срок от 1 секунда до 7 дни, но не и качвания чрез POST формуляри и не и собствени домейни.

Защо моят presigned URL връща SignatureDoesNotMatch?

AWS посочва три чести причини: часовник на компютъра, който не е синхронизиран, прокси, което променя заглавките или query низа, и заявка, чиито метод, заглавки или параметри се различават от подписаните. При качванията обичайният виновник е изпращането на Content-Type, различен от използвания при генерирането на URL адреса.

Източници

Цените и ограниченията са взети от официалните страници по-долу. Доставчиците ги променят, затова проверете, преди да се обвържете.