Можно ли выполнить модифицирующий запрос на другой домен из браузера
Что проверяют
Понимаете ли вы, от чего на самом деле защищает CORS. Типичный неверный ответ «браузер не пустит запрос» показывает, что кандидат не связывает тему с CSRF. Следом спрашивают, как защитить свой API от поддельных запросов с чужих сайтов.
Как отвечать
Можно, и в ряде случаев без всякого разрешения сервера. Same-origin policy запрещает скрипту читать чужой ответ, а не отправлять запрос. Дальше всё зависит от вида запроса:
- простой запрос:
GET,HEADилиPOSTсContent-Typeиз спискаapplication/x-www-form-urlencoded,multipart/form-data,text/plainи без нестандартных заголовков. Браузер отправляет его сразу, сервер его выполняет, а JavaScript просто не получает ответ безAccess-Control-Allow-Origin. Обычная HTML-форма шлёт такой POST на любой домен вообще без скрипта; - запрос с preflight:
PUT,PATCH,DELETE,POSTсapplication/jsonили со своим заголовком вродеAuthorization. Сначала уходитOPTIONSсAccess-Control-Request-Method, и основной запрос отправляется, только если сервер разрешил origin, метод и заголовки черезAccess-Control-Allow-Origin,Access-Control-Allow-MethodsиAccess-Control-Allow-Headers; - cookie: нужны
credentials: 'include'на клиенте иAccess-Control-Allow-Credentials: trueна сервере, причём с конкретным origin, а не*.
Отсюда защита: CSRF-токен, cookie с SameSite=Lax или Strict (Chrome по умолчанию трактует cookie без атрибута как Lax), проверка заголовка Origin на сервере. Когда нужно ходить в чужой API, запрос проксируют через свой бэкенд.
Где спотыкаются
Говорят, что CORS блокирует отправку любого междоменного POST. Тогда непонятно, откуда берутся CSRF-атаки, и интервьюер это сразу заметит.
Предлагают JSONP как способ обхода. Это устаревший приём только для GET, который исполняет чужой скрипт на вашей странице.
Настраивают сервер отражать любой Origin в Access-Control-Allow-Origin вместе с Access-Control-Allow-Credentials: true. Так любой сайт получает право читать ответы от имени залогиненного пользователя.