← Cloudflare R2 / r2 / api / s3
Presigned URLs
Presigned URL представляют собой Концепция S3 ↗ для предоставления временного доступа к объектам без раскрытия ваших API credentials. Presigned URL включает параметры подписи прямо в самом URL, что позволяет любому, у кого есть этот URL, выполнить определённую операцию (например, GetObject или PutObject) к определённому объекту, пока не истечёт срок действия URL.
Они отлично подходят для предоставления временного доступа к отдельным объектам, например, чтобы позволить пользователям загружать файлы напрямую в R2 или выдавать ссылки для скачивания с ограниченным сроком действия.
Чтобы создать presigned URL, укажите:
- Идентификатор ресурса: ID учётной записи, имя бакета и путь к объекту
- Операция: разрешённая операция S3 API (GET, PUT, HEAD или DELETE)
- Срок действия: тайм-аут от 1 секунды до 7 дней (604,800 секунд)
Presigned URL создаются на стороне сервера без обращения к R2: для этого нужны только учётные данные R2 API и реализация алгоритма подписи AWS Signature Version 4.
Выбор подхода
R2 поддерживает два подхода к ограниченному по времени доступу. Они пересекаются по функциям, но имеют разные компромиссы:
| Шаблон | Разрешения | Подходит для |
|---|---|---|
| Presigned URL (эта страница) | Одна операция S3 над одним объектом | Предоставление прямого HTTP-доступа к отдельному объекту без S3-клиента, например для загрузки через браузер или для ссылки на скачивание |
| Временные учётные данные | Несколько операций S3, ограниченных бакетом и набором разрешённых операций, а также, при необходимости, конкретными путями | Вызывающие стороны, использующие стандартный клиент S3 или SDK для выполнения нескольких операций в рамках заданной сессии |
Создание presigned URL
Предварительные требования
- Account ID (для построения URL конечной точки S3)
- R2 API-токен (Access Key ID и Secret Access Key)
- AWS SDK или совместимая клиентская библиотека S3
Примеры SDK
import { S3Client, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const S3 = new S3Client({
region: "auto", // Required by SDK but not used by R2
// Provide your Cloudflare account ID
endpoint: `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`,
// Retrieve your S3 API credentials for your R2 bucket via API tokens (see: https://developers.cloudflare.com/r2/api/tokens)
credentials: {
accessKeyId: '<ACCESS_KEY_ID>',
secretAccessKey: '<SECRET_ACCESS_KEY>',
},
});
// Generate presigned URL for reading (GET)
const getUrl = await getSignedUrl(
S3,
new GetObjectCommand({ Bucket: "my-bucket", Key: "image.png" }),
{ expiresIn: 3600 }, // Valid for 1 hour
);
// https://my-bucket.<ACCOUNT_ID>.r2.cloudflarestorage.com/image.png?X-Amz-Algorithm=...
// Generate presigned URL for writing (PUT)
// Specify ContentType to restrict uploads to a specific file type
const putUrl = await getSignedUrl(
S3,
new PutObjectCommand({
Bucket: "my-bucket",
Key: "image.png",
ContentType: "image/png",
}),
{ expiresIn: 3600 },
);import boto3
s3 = boto3.client(
service_name="s3",
# Provide your Cloudflare account ID
endpoint_url='https://<ACCOUNT_ID>.r2.cloudflarestorage.com',
# Retrieve your S3 API credentials for your R2 bucket via API tokens (see: https://developers.cloudflare.com/r2/api/tokens)
aws_access_key_id='<ACCESS_KEY_ID>',
aws_secret_access_key='<SECRET_ACCESS_KEY>',
region_name="auto", # Required by SDK but not used by R2
)
# Generate presigned URL for reading (GET)
get_url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': 'my-bucket', 'Key': 'image.png'},
ExpiresIn=3600 # Valid for 1 hour
)
# https://my-bucket.<ACCOUNT_ID>.r2.cloudflarestorage.com/image.png?X-Amz-Algorithm=...
# Generate presigned URL for writing (PUT)
# Specify ContentType to restrict uploads to a specific file type
put_url = s3.generate_presigned_url(
'put_object',
Params={
'Bucket': 'my-bucket',
'Key': 'image.png',
'ContentType': 'image/png'
},
ExpiresIn=3600
)# Generate presigned URL for reading (GET)
# The AWS CLI presign command defaults to GET operations
aws s3 presign --endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com \
s3://my-bucket/image.png \
--expires-in 3600
# Output:
# https://<ACCOUNT_ID>.r2.cloudflarestorage.com/my-bucket/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
# Note: The AWS CLI presign command only supports GET operations.
# For PUT operations, use one of the SDK examples above.Полные примеры и дополнительные операции см. в документации для конкретного SDK:
Рекомендации
При создании presigned URL злоупотребления и неправильное использование можно ограничить следующими способами:
- Ограничение Content-Type: укажите допустимые
Content-Typeв параметрах вашего SDK. Подпись будет включать этот заголовок, поэтому загрузки будут завершаться ошибкой с403/SignatureDoesNotMatchошибка, если клиент отправляет другойContent-Typeдля запроса на загрузку. - Настройка CORS: если подписанные URL будут использоваться в браузере, настройте Правила CORS для вашего бакета, чтобы определить, какие источники могут отправлять запросы.
Использование presigned URL
После создания presigned URL используется как обычная конечная точка HTTP. Подпись встроена прямо в URL, поэтому дополнительные заголовки аутентификации не требуются.
# Download using a GET presigned URL
curl "https://my-bucket.<ACCOUNT_ID>.r2.cloudflarestorage.com/image.png?X-Amz-Algorithm=..."
# Upload using a PUT presigned URL
curl -X PUT "https://my-bucket.<ACCOUNT_ID>.r2.cloudflarestorage.com/image.png?X-Amz-Algorithm=..." \
--data-binary @image.pngВы также можете использовать presigned URL напрямую в веб-браузерах, мобильных приложениях или любом HTTP-клиенте. Один и тот же presigned URL можно использовать многократно, пока не истечёт срок его действия.
Пример presigned URL
Ниже приведён пример presigned URL, созданного с использованием учётных данных R2 API и процесса подписи AWS Signature Version 4:
https://my-bucket.123456789abcdef0123456789abcdef.r2.cloudflarestorage.com/photos/cat.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=CFEXAMPLEKEY12345%2F20251201%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20251201T180512Z&X-Amz-Expires=3600&X-Amz-Signature=8c3ac40fa6c83d64b4516e0c9e5fa94c998bb79131be9ddadf90cefc5ec31033&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObjectВ этом примере данный предварительно подписанный URL выполняет GetObject на объекте photos/cat.png в бакете my-bucket в аккаунте с id 123456789abcdef0123456789abcdef. Ключевые параметры подписи, из которых состоит этот заранее подписанный URL, следующие:
X-Amz-Algorithm: указывает алгоритм, использованный для подписи URL.X-Amz-Credential: Содержит информацию об учётных данных, использованных для вычисления подписи.X-Amz-Date: дата и время создания подписи (в формате ISO 8601).X-Amz-Expires: срок действия подписанного URL в секундах, отсчитываемый отX-Amz-Date.X-Amz-Signature: подпись, подтверждающая, что URL был подписан с помощью секретного ключа.X-Amz-SignedHeaders: перечисляет HTTP-заголовки, учтённые при расчёте подписи.
Поддерживаемые операции
R2 поддерживает Presigned URL для следующих HTTP-методов:
GET: Получить объект из бакетаHEAD: получение метаданных объекта из бакетаPUT: загрузка объекта в бакетDELETE: Удалить объект из бакета
POST (загрузка файлов через HTML-формы в формате multipart/form-data) в настоящее время не поддерживается.
Соображения по безопасности
Относитесь к presigned URL как к bearer-токенам. Пока срок действия URL не истек, любой, у кого он есть, может выполнить указанную операцию. Передавайте presigned URL только тем, кому они предназначены, и рассмотрите возможность использования короткого срока действия для операций с конфиденциальными данными.
Пользовательские домены
Presigned URL работают с доменом S3 API (<ACCOUNT_ID>.r2.cloudflarestorage.com) и не может использоваться с пользовательскими доменами.
Если вам нужна аутентификация для бакетов R2, доступных через пользовательские домены (публичных бакетов), используйте Функция проверки HMAC в WAF (требуется план Pro или выше).