Как CORS понимает какой кросс-доменный запрос блокировать?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как CORS понимает какой кросс-доменный запрос блокировать?
CORS (Cross-Origin Resource Sharing) — это механизм безопасности браузера, который контролирует доступ к ресурсам между разными источниками (доменами). Браузер автоматически проверяет специальные HTTP заголовки для определения, разрешён ли запрос.
Что такое Origin (источник)?
Основной параметр для CORS — это Origin, который состоит из трёх частей:
Protocol://Domain:Port
https://example.com:443
https://api.example.com:443
Два запроса имеют РАЗНЫЕ origins, если различаются протокол, домен ИЛИ порт:
https://example.com <- Origin
https://api.example.com <- ДРУГОЙ Origin (разный домен)
https://example.com:8000 <- ДРУГОЙ Origin (разный порт)
http://example.com <- ДРУГОЙ Origin (разный протокол)
Как браузер блокирует кросс-доменные запросы?
1. Браузер отправляет Origin заголовок
Когда ваш JavaScript код на https://frontend.com делает запрос к https://api.com, браузер автоматически добавляет заголовок:
GET /users HTTP/1.1
Host: api.com
Origin: https://frontend.com <- Браузер добавляет автоматически
2. Сервер отвечает с CORS заголовками
Сервер должен ответить с заголовком Access-Control-Allow-Origin:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://frontend.com <- Указывает какой Origin разрешён
Content-Type: application/json
{"data": ...}
3. Браузер проверяет заголовки и принимает решение
// На frontend.com делаем запрос к api.com
fetch('https://api.com/users')
.then(response => response.json())
.catch(error => console.error('CORS Error:', error));
// Браузер проверяет:
// 1. Origin в ответе совпадает с текущим origin?
// 2. Если да - разрешить доступ к данным
// 3. Если нет или заголовок отсутствует - БЛОКИРОВАТЬ (выбросить ошибку)
Практический пример
Сценарий 1: Разрешённый запрос
Фронтенд: https://frontend.com
Бэкенд: https://api.com
Браузер отправляет:
GET /users
Origin: https://frontend.com
Бэкенд отвечает:
Access-Control-Allow-Origin: https://frontend.com <- Совпадает!
Результат: РАЗРЕШЕНО
Сценарий 2: Запрещённый запрос
Фронтенд: https://evil.com
Бэкенд: https://api.com
Браузер отправляет:
GET /users
Origin: https://evil.com
Бэкенд отвечает:
Access-Control-Allow-Origin: https://frontend.com <- НЕ совпадает!
Результат: БЛОКИРОВАНО - CORS Error
Типы запросов и Preflight
Simple Requests (не требуют preflight):
// GET, POST, HEAD с определёнными заголовками
fetch('https://api.com/users');
Complex Requests (требуют preflight проверки):
// PUT, DELETE, PATCH, или специальные заголовки
fetch('https://api.com/users/123', {
method: 'DELETE', // Сложный метод
headers: {
'Authorization': 'Bearer token' // Специальный заголовок
}
});
// Браузер сначала отправляет OPTIONS запрос:
// OPTIONS /users/123
// Origin: https://frontend.com
// Access-Control-Request-Method: DELETE
// Access-Control-Request-Headers: authorization
// Сервер должен ответить:
// Access-Control-Allow-Origin: https://frontend.com
// Access-Control-Allow-Methods: GET, POST, DELETE
// Access-Control-Allow-Headers: Authorization
Основные CORS заголовки
Запрос от браузера:
Origin— откуда идёт запросAccess-Control-Request-Method— какой метод нужен (для preflight)Access-Control-Request-Headers— какие заголовки нужны (для preflight)
Ответ от сервера:
Access-Control-Allow-Origin— какие origins разрешеныAccess-Control-Allow-Methods— какие HTTP методы разрешеныAccess-Control-Allow-Headers— какие заголовки разрешеныAccess-Control-Max-Age— как долго кэшировать preflightAccess-Control-Allow-Credentials— разрешены ли cookies
Конфигурация на бэкенде (пример на Express.js)
const express = require('express');
const app = express();
// Разрешить один конкретный origin
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://frontend.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, PUT');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', 'true');
next();
});
// Или использовать middleware
const cors = require('cors');
app.use(cors({
origin: 'https://frontend.com',
methods: ['GET', 'POST', 'DELETE', 'PUT'],
credentials: true
}));
Частые ошибки
Ошибка 1: Указать wildcard для credentials
// НЕПРАВИЛЬНО - несовместимо
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
// ПРАВИЛЬНО
Access-Control-Allow-Origin: https://frontend.com
Access-Control-Allow-Credentials: true
Ошибка 2: Забыть разрешить методы
// Если frontend отправляет DELETE запрос,
// нужно явно разрешить:
Access-Control-Allow-Methods: GET, POST, DELETE
Выводы
CORS блокирует кросс-доменные запросы на основе:
- Origin заголовка — браузер автоматически указывает источник
- Access-Control-Allow-Origin — сервер указывает разрешённые origins
- Совпадения — если они совпадают, запрос разрешен, нет — блокирован
- Preflight проверка — для сложных запросов браузер сначала проверяет возможность
Это механизм безопасности, который предотвращает злоумышленникам использовать ваши API от имени пользователя.