RFC2617 говорит, чтобы кодировать имя пользователя и пароль для base64, но не сказать, какую кодировку символов использовать при создании октетов для ввода в алгоритм base64.
Должен ли я считать US-ASCII или UTF8? Или кто-то уже решил этот вопрос?
RFC2617 говорит, чтобы кодировать имя пользователя и пароль для base64, но не сказать, какую кодировку символов использовать при создании октетов для ввода в алгоритм base64.
Должен ли я считать US-ASCII или UTF8? Или кто-то уже решил этот вопрос?
RFC 2617 может читаться как "ISO-8859-1" или "undefined". Твой выбор. Известно, что многие серверы используют ISO-8859-1 (нравится это или нет) и потерпит неудачу, когда вы отправите что-то еще. Так что, вероятно, единственный безопасный выбор - придерживаться ASCII.
Для получения дополнительной информации и предложения по исправлению ситуации см. Проект "Параметр кодирования для базовой аутентификации HTTP" (который лег в основу RFC 7617).
С 2015 года существует RFC 7617, который устарел RFC 2617. В отличие от старого RFC, новый RFC явно определяет кодировку символов, которая будет использоваться для имени пользователя и пароля.
charset="UTF-8"
в своем запросе, например так: WWW-Authenticate: Basic realm="myChosenRealm", charset="UTF-8"
Полная версия:
Прочитайте спецификацию. Содержит дополнительные сведения, такие как точная процедура кодирования и список кодовых точек Unicode, которые должны поддерживаться.
Начиная с 2018 года, современные браузеры по умолчанию будут использовать UTF-8, если пользователь вводит не-ASCII-символы для имени пользователя или пароля (даже если сервер не использует параметр charset
).
Параметр области по- прежнему поддерживает только символы ASCII даже в RFC 7617.
Короткий ответ: iso-8859-1, если кодированные слова не используются в соответствии с RFC2047 (MIME).
Более подробное объяснение:
RFC2617, раздел 2 (HTTP-аутентификация) определяет базовые учетные данные:
basic-credentials = base64-user-pass
base64-user-pass = <base64 encoding of user-pass,
except not limited to 76 char/line>
user-pass = userid ":" password
userid = *<TEXT excluding ":">
password = *TEXT
Спецификация не должна читаться без ссылки на RFC2616 (HTTP 1.1) для определений в BNF (например, выше):
Эта спецификация является компаньоном спецификации HTTP/1.1 2. Он использует расширенный раздел 2.1 BNF этого документа и полагается на как нетерминалы, определенные в этом документе, так и другие аспекты спецификация HTTP/1.1.
RFC2616, раздел 2.1 определяет ТЕКСТ (основное внимание):
Правило TEXT используется только для описательного содержимого поля и значений которые не предназначены для интерпретации анализатором сообщений. слова of * TEXT МОЖЕТ содержать символы из наборов символов, отличных от ISO-8859-1 только при кодировании в соответствии с правилами RFC 2047.
TEXT = <any OCTET except CTLs, but including LWS>
Итак, это определенно iso-8859-1, если вы не обнаружите какую-либо другую кодировку в соответствии с правилами RFC2047 (MIME pt. 3):
// Username: Mike
// Password T€ST
Mike:=?iso-8859-15?q?T€ST?=
В этом случае знак евро в слове будет закодирован как 0xA4
в соответствии с iso-8859-15. Я понимаю, что вы должны проверить эти закодированные разделители слов, а затем декодировать слова внутри на основе указанной кодировки. Если вы этого не сделаете, вы подумаете, что пароль =?iso-8859-15?q?T¤ST?=
(обратите внимание, что 0xA4
будет декодироваться до ¤
при интерпретации iso-8859-1).
Это мое понимание, я не могу найти более явное подтверждение, чем эти RFC. И некоторые из них кажутся противоречивыми. Например, одна из 4 заявленных целей RFC2047 (MIME, стр .3) заключается в том, чтобы переопределить:
формат сообщений, позволяющий... текстовую информацию заголовка в наборы символов, отличные от US-ASCII.
Но тогда RFC2616 (HTTP 1.1) определяет заголовок, используя правило TEXT, которое по умолчанию соответствует iso-8859-1. Означает ли это, что каждое слово в этом заголовке должно быть закодированным словом (т.е. Формой =?...?=
)?
Также актуально, что текущий браузер этого не делает. Они используют utf-8 (Chrome, Opera), iso-8859-1 (Safari), системную кодовую страницу (IE) или что-то еще (например, только самый старший бит от utf-8 в случае Firefox).
Изменить: я просто понял, что этот ответ рассматривает проблему больше с точки зрения сервера.
Если вас интересуют, что делают браузеры, когда вы вводите символы не-ascii в приглашении входа в систему, я просто пытался с Firefox.
Кажется, что лениво преобразовать everithing в ISO-8859-1, взяв младший значащий байт каждого значения юникода, например:
User: 豚 (\u8c5a)
Password: 虎 (\u864e)
Закодированы так же, как:
User: Z (\u005a)
Password: N (\u004e)
0x5a 0x3a 0x4e base64- > WjpO
RFCs в Spring framework, BasicAuthenticationFilter
, по умолчанию используется UTF-8.
Поводом для этого выбора я считаю, что UTF-8 способен кодировать все возможные символы, в то время как ISO-8859-1 (или ASCII) - нет. Попытка использования имени пользователя/пароля с символами, не поддерживаемыми в системе, может привести к поломке или (что еще хуже) ухудшению безопасности.
В 2018 году браузеры используют UTF-8. См. Https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#Character_encoding_of_HTTP_authentication