У меня есть приложение Spring Boot, которое обслуживает Restful API. Клиентами являются веб-приложение, мобильное приложение и Postman.
Наша команда безопасности попросила меня внедрить CSRF. Я сделал это, используя цепочку фильтров безопасности и http.csrf(), как это хорошо описано во многих местах, игнорируя конечные точки, такие как вход в систему, которые не требуют аутентификации.
Насколько я понимаю, клиентам необходимо захватить файл cookie с именем XSRF-TOKEN и вернуть его в заголовке X-XSRF-TOKEN с последующими запросами на публикацию, размещение или удаление. Первое, что я сделал, это попытался опубликовать что-нибудь от Postman, чтобы подтвердить, что CSRF действительно включен и блокирует запросы (так и было). Затем я добавил в Postman сценарии предварительного запроса и пост-ответа для захвата и возврата токена, и это тоже работает.
Затем я обратился к мобильному приложению и реализовал ту же стратегию, и она тоже работает.
Я не веб-разработчик, поэтому поручил эту задачу кому-то другому, но потом начал об этом думать. Вся цель файлов cookie заключается в том, чтобы веб-браузер автоматически возвращал значение файла cookie на сервер. В таком случае, почему веб-приложению необходимо явно копировать токен в заголовок? Разве он не должен автоматически просто вернуть этот файл cookie на сервер и не должен ли сервер просто прочитать его из файла cookie? Фактически, Postman также поддерживает файлы cookie, так что там это тоже должно работать.
Я предполагаю, что есть какая-то техническая причина или причина безопасности, почему это не работает, но я действительно не могу понять, что это такое.
Определенно было бы удобнее и надежнее, если бы клиенты могли полагаться на файлы cookie, выполняющие свою работу, вместо того, чтобы каждому клиенту приходилось реализовывать свой собственный код.
Идея копирования значения файла cookie вручную в заголовок основана на том факте, что файл cookie ограничен доменом, для которого он был установлен (это обеспечивается браузером).
из-за этого ТОЛЬКО код js из этого домена может прочитать значение cookie. И поэтому ТОЛЬКО js-код из авторизованного домена может установить правильное значение заголовка.
Поэтому, когда вы получаете фишинговое электронное письмо и непреднамеренно активируете скрытый JS-код для перевода 100 миллионов евро нигерийскому принцу, браузер по умолчанию включит значение файла cookie, НО JS-код нигерийского члена королевской семьи не сможет прочитать и, следовательно, не сможет включить значение CSRF в заголовок.
Таким образом сервер узнает, что это был несанкционированный вызов API, и вернет ответ 403
, например, из-за CSRF-фильтра в Spring-Security.
Проблема, с которой мы сейчас столкнулись, заключается в том, что наше веб-приложение не может прочитать файл cookie, содержащий токен csrf. Мы думаем, что это, вероятно, потому, что домен нашего веб-сервера отличается от домена сервера REST API. Я пытался найти способ извлечь токен из ответа перед его отправкой и скопировать его в обычный заголовок, но мне так и не удалось его увидеть.
Имеет смысл. Спасибо за объяснение!