Почему конфиденциальные данные (пароли, токены) следует передавать в теле (Body) HTTP-запроса, а не в URL?

«Почему конфиденциальные данные (пароли, токены) следует передавать в теле (Body) HTTP-запроса, а не в URL?» — вопрос из категории Безопасность, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Передача конфиденциальных данных в теле запроса (обычно через POST/PUT) безопаснее, чем в строке запроса (URL), из-за следующих рисков URL:

  1. Логирование: URL часто попадает в логи веб-серверов, прокси, браузеров и аналитических систем, становясь доступным третьим лицам.
  2. История браузера и закладки: URL с параметрами сохраняется в истории браузера и может быть добавлен в закладки.
  3. Referer header: При переходе по ссылке полный URL (включая параметры) может отправляться на следующий сайт через HTTP-заголовок Referer.
  4. Ограничение длины: Серверы и браузеры имеют лимит на длину URL (обычно ~2000 символов).

Ключевое уточнение: При использовании HTTPS и тело запроса, и заголовки (включая путь URL) шифруются при передаче по сети. Однако риски логирования и хранения (пункты 1-3) остаются, так как данные из URL видны на стороне сервера и клиента до/после шифрования.

Пример (Java HttpClient):

// ❌ Рискованно: данные в URL
String urlUnsafe = "https://api.example.com/login?username=admin&token=secret123";

// ✅ Безопасно: данные в теле запроса
String requestBody = "{"username":"admin","token":"secret123"}";

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://api.example.com/login"))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(requestBody))
        .build();