Вопрос или проблема
Резюме
В настоящее время я пытаюсь создать веб-сайт, который отображает частные видео в зависимости от прав пользователей. Я размещаю фронтенд с помощью NextJS (http://localhost:3000) и бэкэнд с помощью NestJS (http://localhost:5000). Я храню видео в частном S3 бакете и использую CloudFront для генерации подписанных куки (если пользователь авторизован) и отображения контента.
Проблема
Если я получаю доступ к видео напрямую https://xxxxxx.cloudfront.net/video/intro.mp4
, и куки: CloudFront-Key-Pair-Id
, CloudFront-Policy
, CloudFront-Signature
правильно хранятся в браузере, я могу без проблем просмотреть видео. Однако, если я пытаюсь воспроизвести это в моем видеоплеере в приложении NextJS по адресу (http://localhost:3000)
, видео не воспроизводится и возвращается сообщение 'http://localhost:3000' заблокирован политикой CORS: Отсутствует заголовок 'Access-Control-Allow-Origin' в запрашиваемом ресурсе.
.
Настройка
S3 Бакет
Политика CORS
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"https://xxxxxxx.cloudfront.net"
],
"ExposeHeaders": [
"ETag",
"Access-Control-Allow-Origin"
]
}
]
Политика Бакета
{
"Version": "2008-10-17",
"Id": "PolicyForPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::xxxxx-private/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::xxxxxx"
}
}
}
]
}
CloudFront
Политика Запроса Происхождения
NestJS
Главное
app.enableCors({
origin: 'http://localhost:3000',
credentials: true,
});
Контроллер
async access() {
const cookies = await this.service.getAccess(id);
response.cookie(
'CloudFront-Key-Pair-Id',
cookies['CloudFront-Key-Pair-Id'],
{
domain: 'localhost',
httpOnly: true,
},
);
response.cookie('CloudFront-Policy', cookies['CloudFront-Policy'], {
domain: 'localhost',
httpOnly: true,
});
response.cookie(
'CloudFront-Signature',
cookies['CloudFront-Signature'],
{
domain: 'localhost',
httpOnly: true,
},
);
return 'Успех';
}
NextJS
API вызов
const response = await axios.get(`${this.client}/${url}`, {
headers: {
...headers,
Authorization: `Bearer ${getCookie("Access-Token")}`,
},
withCredentials: true,
});
Ошибка
'http://localhost:3000' заблокирован политикой CORS: Отсутствует заголовок 'Access-Control-Allow-Origin' в запрашиваемом ресурсе.
Ответ или решение
Решение проблемы с воспроизведением видео в Next.js с использованием подписанных куки CloudFront
Введение
Создание веб-сайта, отображающего частные видео, требует не только правильной настройки серверной и клиентской частей, но и учета аспектов безопасности, включая контроль доступа. В вашем случае использование Amazon S3 для хранения видео и CloudFront для генерации подписанных куков представляет собой хорошее решение. Однако проблема с CORS (Cross-Origin Resource Sharing) мешает вам воспроизводить видео в приложении Next.js, даже несмотря на то, что прямой доступ к видео через CloudFront работает корректно.
Основные причины проблемы
Ваше сообщение указывает на несколько ключевых элементов, которые могут вызывать ошибку CORS:
-
CORS-политика S3: Несмотря на то что политика CORS настроена, возможно, что настройка не соответствует вашему сценарию использования.
-
Куки для CloudFront: Возможно, куки недоступны в запросе, выполняемом на стороне клиента (Next.js), или их формат неправильно задан.
-
Заголовки запроса: Запрос из вашего приложения Next.js может не содержать необходимые заголовки, позволяющие браузеру интерпретировать ответ из CloudFront правильно.
Решения
1. Исправление CORS-политики S3
Убедитесь, что CORS-политика вашей корзины S3 настроена правильно и разрешает доступ из вашего локального домена. Попробуйте обновить политику CORS следующим образом:
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET"],
"AllowedOrigins": ["http://localhost:3000", "https://xxxxxxx.cloudfront.net"],
"ExposeHeaders": ["ETag", "Access-Control-Allow-Origin"]
}
]
Добавление http://localhost:3000
в список разрешенных источников позволяет вашему приложению Next.js делать запросы к S3.
2. Обработка куков
Обратите внимание на настройку куков для CloudFront. Убедитесь, что куки не имеют свойства httpOnly
, так как это предотвращает доступ к ним из клиентского JavaScript. Параметры куков можно настроить следующим образом:
response.cookie(
'CloudFront-Key-Pair-Id',
cookies['CloudFront-Key-Pair-Id'],
{
domain: 'localhost', // лучше использовать только имя вашего домена
secure: process.env.NODE_ENV === 'production', // если приложение в продакшен
sameSite: 'None', // необходимо для куков с CORS
}
);
3. Настройка запросов Axios в Next.js
Когда вы делаете запрос из Next.js, убедитесь, что передаете куки с запросом:
const response = await axios.get(`${this.client}/${url}`, {
headers: {
...headers,
Authorization: `Bearer ${getCookie("Access-Token")}`,
},
withCredentials: true // важный параметр для передачи куков
});
4. Проверка статуса запросов
Не забудьте использовать инструменты разработчика в браузере (например, Chrome DevTools), чтобы проверить заголовки запросов и ответов, а также статус любых запросов, которые вызывают проблемы. Это поможет понять, правильно ли настроены CORS.
Заключение
Проблема с воспроизведением видео в Next.js с использованием CloudFront и подписанных куков может быть решена путем тщательной настройки политики CORS на S3, изменения параметров куков и правильной конфигурации запросов Axios. Пошаговое следование рекомендациям улучшит доступность ваших видеофайлов для авторизованных пользователей. Если после внесения изменений проблема останется, проверьте журнал ошибок CloudFront и S3 для получения дополнительной информации.