Яке кодування слід використовувати для базової автентифікації HTTP?


85

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

Чи слід приймати US-ASCII або UTF8? Або хтось уже десь вирішив це питання?


Відповіді:


72

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

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

Для отримання додаткової інформації та пропозиції щодо виправлення ситуації див. Проект "Параметр кодування для базової автентифікації HTTP" (який склав основу для RFC 7617).

Нове - RFC 7617

З 2015 року існує RFC 7617 , який застаріває RFC 2617. На відміну від старого RFC, новий RFC чітко визначає кодування символів, яке використовуватиметься для імені користувача та пароля.

  • Кодування за замовчуванням все ще не визначено. Is необхідний лише для сумісності з 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 )

Царство

Параметр області все ще підтримує лише символи ASCII, навіть у RFC 7617.


Дякую Джуліану. Я натрапив на цю пропозицію, але, схоже, термін дії минув і нікуди не пішов далі. Шкода :-(.
Добес Вандермеер

1
Ваша відповідь повинна бути найкращою. Я можу перефразувати це як ASCII точно, можливо ISO-8859-1, якщо вам пощастить.
Добес Вандермеер,

Схоже, остання версія 04 пропозиції (яка, за збігом обставин, здається, опублікована сьогодні) закінчується 1 серпня 2012 р.
Michiel van Oosterhout

Відповідь застаріла, оскільки в ній не згадувалось RFC 7617. Я редагував, щоб включити це. Джуліан: Сподіваюся, ви не проти.
sleske

На жаль, я щойно зрозумів, що ви насправді є автором RFC 7617. Тепер я справді сподіваюся, що я щось неправильно відредагував.
sleske

41

Коротка відповідь: 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 використовується лише для описового вмісту поля та значень, які не призначені для інтерпретації аналізатором повідомлень. Слова * TEXT МОЖУТЬ містити символи з наборів символів, відмінних від ISO-8859-1, лише у випадку кодування згідно з правилами RFC 2047.

TEXT           = <any OCTET except CTLs, but including LWS>

Тож це точно iso-8859-1, якщо ви не виявите якесь інше кодування згідно з правилами RFC2047 (MIME, п. 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).

Редагувати: Я щойно зрозумів, що ця відповідь розглядає проблему більше з точки зору сервера.


Кодування RFC 2047 у цьому випадку не застосовується.
Джуліан Решке

@JulianReschke Ну, в специфікації чітко зазначено "лише в тому випадку, коли кодовано відповідно до правил RFC 2047". Я розумію, що правила RFC2047 можуть не застосовуватися до заголовків HTTP, але специфікація досить чітка, посилаючись на неї. Я додав той факт, що жоден браузер насправді цього не робить.
Michiel van Oosterhout

4
специфікації HTTPbis більше не згадуватимуть RFC 2047.
Джуліан Решке

Дуже детальний запис, спасибі @MichielvanOosterhout!
ToastyMallows

5

За винятком RFC, у Spring , BasicAuthenticationFilterкласі, за замовчуванням UTF-8 .

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


1
Ну, використання UTF-8 не допомагає, якщо інша сторона не знає про це. Тож було б непогано, якби фреймворк Spring реалізував параметр кодування, описаний у < greenbytes.de/tech/webdav/rfc7617.html#rfc.section.2.1 >
Джуліан Решке

1
@JulianReschke Я повідомив, як це реалізовано в одному з найпоширеніших фреймворків та ймовірна причина цього. Не стріляйте в месенджер!
holmis83

4

Якщо вас цікавить, що роблять браузери, коли ви вводите символи, що не є ascii, у рядку входу, я щойно спробував із Firefox.

Здається, ліниво перетворює everithing на ISO-8859-1, беручи найменш значущий байт кожного значення Unicode, наприклад:

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

Кодуються так само, як:

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

0x5a 0x3a 0x4e base64-> WjpO


1
Так, така стара поведінка у Firefox. Його було змінено (схоже на V57) і тепер замість нього використовується UTF-8.
sleske

1
V59, а не V57. В даний час у бета-тесті.
Джуліан Решке
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.