Какую кодировку следует использовать для базовой аутентификации HTTP? - PullRequest
72 голосов
/ 30 августа 2011

RFC2617 говорит, что кодирует имя пользователя и пароль в base64, но не говорит, какую кодировку символов использовать при создании октетов для ввода в алгоритм base64.

Должен ли я принимать US-ASCII или UTF8? Или кто-то уже где-то решил этот вопрос?

Ответы [ 4 ]

57 голосов
/ 30 августа 2011

Оригинальная спецификация - RFC 2617

RFC 2617 может читаться как "ISO-8859-1" или "undefined". Твой выбор. Известно, что многие серверы используют ISO-8859-1 (нравится это или нет) и потерпит неудачу, когда вы отправите что-то еще. Так что, вероятно, единственный безопасный выбор - придерживаться ASCII.

Для получения дополнительной информации и предложения по исправлению ситуации см. Проект «Параметр кодирования для базовой аутентификации HTTP» (который лег в основу RFC 7617).

Новый - RFC 7617

С 2015 года существует RFC 7617 , который устарел RFC 2617. В отличие от старого RFC, новый RFC явно определяет кодировку символов, которая будет использоваться для имени пользователя и пароля.

  • Кодировка по умолчанию все еще не определена. Требуется только совместимость с US-ASCII (это означает, что он сопоставляет байты ASCII с байтами ASCII, как это делает UTF-8).
  • Сервер может дополнительно отправить дополнительный параметр аутентификации charset="UTF-8" в своем вызове, например:
    WWW-Authenticate: Basic realm="myChosenRealm", charset="UTF-8"
    Это объявляет, что сервер будет принимать не-ASCII-символы в имени пользователя / пароле и ожидает, что они будут закодированы в UTF-8 (в частности, форма нормализации C). Обратите внимание, что допускается только UTF-8.

Полная версия:

Чтение спецификация . Если содержит дополнительные сведения, такие как точная процедура кодирования и список кодовых точек Unicode, которые должны поддерживаться.

Поддержка браузера

Начиная с 2018 года, современные браузеры будут по умолчанию использовать UTF-8, если пользователь вводит не-ASCII символы для имени пользователя или пароля (даже если сервер не использует параметр charset).

  • Chrome также использует UTF-8
  • Internet Explorer не использует UTF-8 ( выпуск # 11879588 )
  • Firefox экспериментирует с изменением, запланированным в настоящее время для v59 ( ошибка 1419658 )

Realm

Параметр realm по-прежнему поддерживает только символы ASCII даже в RFC 7617.

37 голосов
/ 30 января 2012

Краткий ответ: iso-8859-1, если кодированные слова не используются в соответствии с RFC2047 (MIME).

Более длинное объяснение:

RFC2617, раздел 2 (HTTP-аутентификация) определяет basic-credentials :

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 БНФ этого документа и опирается на как нетерминалы, определенные в этом документе, так и другие аспекты спецификация HTTP / 1.1.

RFC2616, раздел 2.1 определяет ТЕКСТ (выделено мной):

Правило TEXT используется только для описания содержимого полей и значений которые не предназначены для интерпретации анализатором сообщений. слова из * 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, pt. 3) - переопределить:

формат сообщений, позволяющих ... текстовую информацию заголовка в наборы символов, отличные от US-ASCII.

Но тогда RFC2616 (HTTP 1.1) определяет заголовок, используя правило TEXT, которое по умолчанию iso-8859-1. Означает ли это, что каждое слово в этом заголовке должно быть закодированным (то есть формой =?...?=)?

Также актуально, ни один браузер этого не делает. Они используют utf-8 (Chrome, Opera), iso-8859-1 (Safari), системную кодовую страницу (IE) или что-то еще (например, только самый значимый бит из utf-8 в случае Firefox).

Редактировать: я только что понял, что этот ответ смотрит на проблему больше с точки зрения сервера.

4 голосов
/ 13 февраля 2017

RFC в стороне, в Spring Framework , класс BasicAuthenticationFilter, по умолчанию UTF-8 .

Причина такого выбора, на мой взгляд, заключается в том, что UTF-8 способен кодировать все возможные символы, а ISO-8859-1 (или ASCII) - нет. Попытка использовать имя пользователя / пароль с символами, не поддерживаемыми в системе, может привести к нарушению поведения или (возможно, к худшему) снижению безопасности.

4 голосов
/ 05 августа 2016

Если вам интересно, что делают браузеры, когда вы вводите не-ascii символы в приглашении для входа в систему, я только что попробовал с Firefox.

Кажется, что лениво конвертировать все в ISO-8859-1, взявмладший значащий байт каждого значения Юникода, например:

User: 豚 (\u8c5a)
Password: 虎 (\u864e)

Кодируются так же, как:

User: Z (\u005a)
Password: N (\u004e)

0x5a 0x3a 0x4e base64-> WjpO

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...