CORS
CORS (Cross-Origin Resource Sharing, Fetch spec) — механизм, позволяющий серверу разрешить браузеру делать запросы с других origin. По умолчанию — Same-Origin Policy запрещает.
Что такое origin
scheme://host:port. Разный порт или scheme — уже другой origin. https://a.com и https://a.com:8080 — разные.
Simple request
GET/HEAD/POST с "простыми" заголовками — браузер шлёт запрос сразу, потом смотрит ответ.
GET /api/data HTTP/1.1
Origin: https://frontend.com
# Response
Access-Control-Allow-Origin: https://frontend.com
Preflight (OPTIONS)
Для "сложных" запросов (PUT/DELETE, Custom-Header, Content-Type: application/json) браузер сначала шлёт OPTIONS:
OPTIONS /api/data
Origin: https://frontend.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: Authorization
# Response
Access-Control-Allow-Origin: https://frontend.com
Access-Control-Allow-Methods: GET, POST, DELETE
Access-Control-Allow-Headers: Authorization
Access-Control-Max-Age: 86400
Credentials (куки)
Чтобы браузер слал куки/Authorization:
- Клиент:
fetch(url, {credentials: 'include'}) - Сервер:
Access-Control-Allow-Credentials: true - При этом нельзя использовать
*— только конкретный origin
Wildcard vs echo
# всем можно, без куки
Access-Control-Allow-Origin: *
# whitelist через Vary
Access-Control-Allow-Origin: https://frontend.com
Vary: Origin
Не защищает от CSRF
CORS — про чтение. Запрос уходит и обрабатывается серверу даже без CORS-заголовков; браузер просто не даёт JS прочитать ответ. Для защиты от CSRF нужны CSRF-токены или SameSite.