Вопрос или проблема
Рекомендуется часто делать это в веб-приложениях:
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
// Определите разрешенные источники
const allowedOrigins = [
'http://localhost:3000',
'http://localhost:3001',
'http://localhost:3002',
'http://localhost:3003',
'https://my.site',
]
export function middleware(request: NextRequest) {
// Получите источник из заголовков запроса
const origin = request.headers.get('origin')
// Если источник не в списке разрешенных, верните null в заголовке
const corsOrigin =
origin && allowedOrigins.includes(origin)
? origin
: allowedOrigins[0]
// Обработка предварительного запроса OPTIONS
if (request.method === 'OPTIONS') {
return NextResponse.json(
{},
{
headers: {
'Access-Control-Allow-Origin': corsOrigin,
'Access-Control-Allow-Methods':
'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
},
},
)
}
// Обработка самого запроса
const response = NextResponse.next()
// Добавление заголовков CORS в ответ
response.headers.set('Access-Control-Allow-Origin', corsOrigin)
response.headers.set(
'Access-Control-Allow-Methods',
'GET, POST, PUT, DELETE, OPTIONS',
)
response.headers.set(
'Access-Control-Allow-Headers',
'Content-Type, Authorization',
)
return response
}
// Настройте, какие маршруты используют этот промежуточный слой
export const config = {
matcher: '/:path*',
}
Здесь это промежуточное ПО Next.js, которое проверяет, находитесь ли вы на localhost, и разрешает любые запросы.
Разве это не очень небезопасно? Или, по крайней мере, хакер может обойти ваш веб-сайт и делать API-запросы, если они загрузят его в Puppeteer или что-то подобное и сделают HTTP/REST-запросы с “localhost”. Puppeteer — это API браузера в Node.js для веб-автоматизации.
Итак, если бы я был хакером, я бы создал веб-приложение, загрузил бы его на localhost и сделал бы запрос из фронтенда localhost к любому бэкенд API, который хочу. Возможно, есть более простой способ взломать по подобным линиям, но да.
Как я могу разрешить CORS для localhost (чтобы я мог тестировать на сервере API в производственной среде), но только для себя, а не для кого-либо другого?
Ответ или решение
Вопрос о безопасном использовании CORS для локального доступа к API, без раскрытия его для нежелательных пользователей, является весьма актуальным для разработчиков, работающих с веб-приложениями. В этой статье мы разберем, как правильно настроить CORS, позволяя доступ только с вашего локального окружения, и предотвратив возможные атаки.
Основные понятия CORS и его важность
CORS (Cross-Origin Resource Sharing) — это механизм, который позволяет ограничить доступ к ресурсам веб-приложений на основе их источника. Это особенно важно для защиты ваших API от несанкционированных запросов с других доменов. Если CORS настроен неправильно, это может открыть двери для хакеров, которые могут использовать инструменты, такие как Puppeteer, для выполнения любых запросов от своего локального окружения.
Актуальная реализация CORS в Next.js
Представленный код в вопросе содержит логику для разрешения CORS только для определенных источников. Давайте углубимся в детали:
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
// Определяем разрешенные источники
const allowedOrigins = [
'http://localhost:3000',
'http://localhost:3001',
'http://localhost:3002',
'http://localhost:3003',
'https://my.site',
]
export function middleware(request: NextRequest) {
// Получаем источник из заголовков запроса
const origin = request.headers.get('origin')
// Проверяем, находится ли источник в списке разрешенных
const corsOrigin =
origin && allowedOrigins.includes(origin)
? origin
: allowedOrigins[0]
// Обработка preflight-запроса OPTIONS
if (request.method === 'OPTIONS') {
return NextResponse.json(
{},
{
headers: {
'Access-Control-Allow-Origin': corsOrigin,
'Access-Control-Allow-Methods':
'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
},
},
)
}
// Обработка фактического запроса
const response = NextResponse.next()
// Добавляем заголовки CORS к ответу
response.headers.set('Access-Control-Allow-Origin', corsOrigin)
response.headers.set(
'Access-Control-Allow-Methods',
'GET, POST, PUT, DELETE, OPTIONS',
)
response.headers.set(
'Access-Control-Allow-Headers',
'Content-Type, Authorization',
)
return response
}
// Конфигурация маршрутов для использования этого middleware
export const config = {
matcher: '/:path*',
}
Проблемы, связанные с безопасностью
Как было указано в вопросе, такой подход может показаться небезопасным. Хакеры могут создать веб-приложение, запущенное на localhost
, и отправлять запросы к вашему API. Чтобы избежать этого, существует несколько стратегий.
Рекомендации по безопасной настройке CORS
-
Проверка IP-адреса:
Вместо того, чтобы полагаться только наorigin
, вы можете проверять IP-адресы исходящих запросов. Например, вы можете разрешать доступ только с вашего локального IP-адреса. -
Ограничение на основе токенов:
Используйте механизмы аутентификации, такие как OAuth или JWT. Это добавит уровень защиты, требуя проверки токенов для доступа к API. -
Настройка окружения:
Убедитесь, что ваши настройки CORS и API доступны только в девелоперском окружении. На продакшене следует использовать более строгие правила и избегать разрешенияlocalhost
для всех. -
Локальные токены:
Задать специальный токен доступа для локальной разработки. Токен должен быть известен только вам, и все запросы к API должны использовать этот токен. -
Использование прокси:
Настройте прокси-сервер для своих локальных приложений. Это добавит дополнительный уровень, позволяя вам контролировать доступ.
Заключение
Настройка CORS для локального доступа к API — это важный шаг в обеспечении безопасности ваших веб-приложений. Подходы, описанные выше, помогут минимизировать риски и protéger ваши ресурсы от нежелательного доступа. Правильная реализация CORS, основанная на проверке источников и соблюдении принципов безопасности, значительно повысит защищенность вашего API.