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 — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки