Вопрос или проблема
Я автоматизирую веб-сайт, который требует базовую аутентификацию HTTP.
Рекомендации, представленные по этой ссылке, работают безотказно в большинстве случаев:
Можно ли передать пользователя/пароль для базовой аутентификации HTTP в параметрах URL?
Тем не менее, у некоторых пользователей в пароле есть вопросительный знак (?
).
Пожалуйста, подскажите, как экранировать вопросительный знак.
P. S.
Я знаю, что @
в имени пользователя можно экранировать как %40
.
Я предполагаю, что вы должны ссылаться на часть URL userinfo, в которой передаются учетные данные пользователя, а не на “параметры URL” (которые являются частью query-string):
https://<userinfo>@example.com/foo?<query-string>
Как и любой символ, который не разрешен в любой части URL (поскольку он может иметь специальное значение), его необходимо закодировать в URL (кодирование процентов) как %
, за которым следует двухзначный шестнадцатеричный код этого символа.
Таким образом, @
это %40
, а ?
это %3F
.
Но это не единственные два символа, которые могут потребовать URL-кодирования. Вы должны передать значение через функцию URL-кодирования в вашем скрипте, чтобы правильно закодировать эту часть URL.
RFC 3986 определяет, какие символы разрешены (без кодирования) в части URL userinfo:
userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" pct-encoded = "%" HEXDIG HEXDIG sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
Таким образом, все остальное должно быть закодировано в процентах, включая :
и %
– если они являются частью user или password (чтобы нейтрализовать их специальное значение).
Также указано в том же документе:
Использование формата “user:password” в поле userinfo устарело.
Следовательно, поддержка в браузерах была непостоянной, она появлялась и исчезала в разных версиях (первостепенное внимание уделяется безопасности). Я полагаю, что последние версии Chrome (тестировалось в версии 79) и Firefox поддерживают учетные данные пользователей в URL. Я видел комментарии, что это также работает в последнем Safari(?), хотя это не работало долгое время, и в данный момент не работает для меня (хотя я не использую последнюю версию на iOS 12.4.1). А браузер IE перестал поддерживать имена пользователей и пароли в URL несколько лет назад, и похоже, это не вернется.
На указанном выше сайте MS есть способ отключить это поведение. Поэтому IE все еще может это делать.
Ответ или решение
Автоматизация веб-сайта, который требует базовую HTTP-аутентификацию, может столкнуться с определёнными проблемами, включая сложности с передачей учётных данных, в частности, когда пароль пользователя содержит специальные символы, такие как вопросительный знак (?
). В таких случаях правильное кодирование символов в URL становится важной задачей.
Теория
HTTP-аутентификация чаще всего использует схему, известную как Basic Authentication, в которой учётные данные пользователя (логин и пароль) передаются в заголовках HTTP-запроса. Однако, исторически сложилось так, что можно передавать учётные данные в URL, используя секцию userinfo
. Это делается через формат, который включает в себя логин и пароль, разделённые двоеточием, до указания основного домена: https://username:password@example.com
.
Тем не менее, эта практика оригинально не рекомендована, как указано в RFC 3986, из-за ряда причин, таких как безопасность и поддержка разными браузерами. Вместо этого, использование заголовков авторизации остаётся более безопасной и надёжной практикой.
В тех случаях, когда необходимо использовать userinfo
, важно понимать, что URL структурировано в соответствии с особым набором правил, в которых некоторые символы имеют специальное значение и должны быть закодированы через процентное кодирование (percent-encoding). Это кодирование заключается в использовании символа %
, за которым следуют два шестнадцатеричных символа, представляющих ASCII код символа. Например, символ ?
кодируется как %3F
, а символ @
как %40
.
Пример
Представим сайт, который требуется аутентифицировать пользователя с паролем, содержащим ?
. Когда учётные данные включены непосредственно в URL, это может привести к ошибке, так как ?
является зарезервированным символом, который обозначает начало строки запроса (query string). Кодирование символа с помощью процентного кодирования позволяет избежать конфликта, гарантируя правильную интерпретацию URL.
Пример:
https://user:pa%3Fsword@example.com
В этом примере пароль pa?sword
был преобразован в pa%3Fsword
, что позволяет безопасно передать его в URL.
Применение
Чтобы реализовать это на практике, рекомендуется использовать функции URL-кодирования, доступные в большинстве языков программирования и библиотек для работы с HTTP-запросами. Например, в Python это можно сделать с помощью модуля urllib
.
import urllib.parse
username = "user"
password = "pa?sword"
encoded_password = urllib.parse.quote(password, safe='')
url = f"https://{username}:{encoded_password}@example.com"
Этот скрипт безопасно кодирует пароль и вставляет его в URL. Такая практика гарантирует, что все символы, которые могут иметь специальное значение в URL, будут корректно обработаны.
Ограничения и рекомендации
-
Безопасность: Хранение и передача паролей в URL создаёт риски для безопасности. URL могут быть сохранены в логах, истории браузеров и бути замечены другими на промежуточных серверных узлах. Используйте заголовки авторизации там, где это возможно.
-
Поддержка браузеров: С поддержкой учётных данных в URL связаны ограничения. Браузеры могут некорректно обрабатывать такие запросы. В текущих версиях Chrome и Firefox это может работать, но в IE и Safari поддержки может не быть.
-
Депрекация: Практика использования
userinfo
с паролями считается устаревшей, и вы должны ожидать, что поддержка будет со временем исчезать. Разработайте своё приложение с учётом возможных изменений в будущем.
Таким образом, кодирование специальных символов в URL для HTTP-аутентификации — это лишь временное решение, которое следует использовать с осторожностью и проводить все операции с учётом безопасности данных пользователей.