GET для сброса пароля — это дыра, даже если токен длинный

В коде на ревью видно: контроллер принимает GET /reset-password?token=xxx и сразу внутри обработчика сбрасывает пароль и шлёт новый на почту. Токен криптостойкий, казалось бы — что не так.

Проблема не в токене, а в семантике HTTP-метода. GET обязан быть safe (не менять состояние) и idempotent (повторный вызов не должен иметь дополнительного эффекта). Сброс пароля — явное изменение состояния системы.

Почему это не теория, а реальная уязвимость. Ссылку из письма видят не только пользователь и сервер — её видят прокси-кеши, антивирусы с предпросмотром ссылок, браузерные префетчеры, которые открывают ссылки со страницы заранее, чтобы ускорить переход. Любой из них может дёрнуть GET по этому URL раньше пользователя — и токен будет использован третьей стороной до того, как владелец вообще открыл письмо.

Есть и вторая часть проблемы: сам GET-запрос с токеном в query string оседает в логах прокси, в истории браузера, в заголовке Referer при переходе на внешний ресурс со страницы сброса. Токен из одноразового превращается в долгоживущий секрет, доступный куче промежуточных систем.

@GetMapping("/reset-password") public String showResetForm(@RequestParam String token) { // только показать форму, НЕ менять состояние return "reset-form"; }

@PostMapping("/reset-password") public ResponseEntity resetPassword(@RequestParam String token, @RequestBody NewPasswordRequest body) { // здесь — реальный сброс пароля }

На собеседовании следом обычно спрашивают: «а кому вообще виден HTTP-ответ GET-запроса, кроме клиента?» Правильный ответ — любому промежуточному узлу на пути: CDN, корпоративному прокси с кешированием, логирующему middleware. Отсюда и вывод: GET годится для безопасного показа формы, сам сброс — только через POST, который явно меняет состояние и не кешируется по умолчанию.

Правило простое: если запрос меняет состояние системы, метод не GET — независимо от того, насколько секретным выглядит параметр.

Тренажёр: 900+ вопросов и задач, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки