Jakiego kodowania należy używać do podstawowego uwierzytelniania HTTP?

85

RFC2617 mówi, że należy zakodować nazwę użytkownika i hasło do base64, ale nie mówi, jakiego kodowania znaków użyć podczas tworzenia oktetów do wprowadzenia do algorytmu base64.

Czy powinienem założyć US-ASCII czy UTF8? A może ktoś już gdzieś rozstrzygnął tę kwestię?

Dobes Vandermeer
źródło

Odpowiedzi:

72

Oryginalna specyfikacja - RFC 2617

RFC 2617 można odczytać jako „ISO-8859-1” lub „niezdefiniowany”. Twój wybór. Wiadomo, że wiele serwerów używa ISO-8859-1 (podoba lub nie) i zawiedzie, gdy wyślesz coś innego. Więc prawdopodobnie jedynym bezpiecznym wyborem jest trzymanie się ASCII.

Aby uzyskać więcej informacji i propozycję rozwiązania problemu, zobacz wersję roboczą „Parametr kodowania dla podstawowego uwierzytelniania HTTP” (który stanowił podstawę dla RFC 7617).

Nowość - RFC 7617

Od 2015 roku istnieje RFC 7617 , który zastępuje RFC 2617. W przeciwieństwie do starego RFC, nowy RFC wyraźnie definiuje kodowanie znaków, które mają być używane dla nazwy użytkownika i hasła.

  • Domyślne kodowanie jest nadal niezdefiniowane. Wymagane jest tylko, aby był zgodny z US-ASCII (co oznacza, że ​​mapuje bajty ASCII na bajty ASCII, tak jak robi to UTF-8).
  • Serwer może opcjonalnie wysłać dodatkowy parametr uwierzytelniania charset="UTF-8"w swoim wezwaniu, na przykład:
    WWW-Authenticate: Basic realm="myChosenRealm", charset="UTF-8"
    To ogłasza, że ​​serwer zaakceptuje znaki inne niż ASCII w nazwie użytkownika / haśle i oczekuje, że zostaną one zakodowane w UTF-8 (w szczególności formularz normalizacji C) . Zwróć uwagę, że dozwolony jest tylko UTF-8.

Pełna wersja:

Przeczytaj specyfikację . Jeśli zawiera dodatkowe szczegóły, takie jak dokładna procedura kodowania i lista punktów kodowych Unicode, które powinny być obsługiwane.

Wsparcie przeglądarki

Począwszy od 2018 r., Nowoczesne przeglądarki będą zwykle domyślnie używać UTF-8, jeśli użytkownik wprowadzi znaki inne niż ASCII jako nazwę użytkownika lub hasło (nawet jeśli serwer nie używa tego charsetparametru).

  • Wygląda na to, że Chrome używa UTF-8
  • Internet Explorer nie używa UTF-8 ( numer wydania 11879588 )
  • Firefox eksperymentuje ze zmianą obecnie planowaną dla wersji 59 ( błąd 1419658 )

Królestwo

Sfera parametr nadal obsługuje tylko znaki ASCII nawet w dokumencie RFC 7617.

Julian Reschke
źródło
Dzięki Julian. Spotkałem się z tą propozycją, ale wydaje się, że wygasła i nie poszedłem dalej. Szkoda :-(.
Dobes Vandermeer
1
Twoja odpowiedź musi być najlepsza. Na pewno mogę sparafrazować to jako ASCII, może ISO-8859-1, jeśli masz szczęście.
Dobes Vandermeer
Wygląda na to, że najnowsza wersja 04 propozycji (która przypadkowo wydaje się opublikowana dzisiaj) wygasa 1 sierpnia 2012.
Michiel van Oosterhout
Odpowiedź była przestarzała, ponieważ nie wspominała o RFC 7617. Edytowałem, aby to uwzględnić. Julian: Mam nadzieję, że nie masz nic przeciwko.
sleske
Ups - właśnie zdałem sobie sprawę, że faktycznie jesteś autorem RFC 7617. Teraz mam nadzieję, że nie pomyliłem czegoś źle.
sleske
41

Krótka odpowiedź: iso-8859-1, chyba że zakodowane słowa są używane zgodnie z RFC2047 (MIME).

Dłuższe wyjaśnienie:

RFC2617, sekcja 2 (Uwierzytelnianie HTTP) definiuje podstawowe poświadczenia :

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

Specyfikacji nie należy czytać bez odwołania się do RFC2616 (HTTP 1.1) dla definicji w BNF (jak powyższa):

Ta specyfikacja jest uzupełnieniem specyfikacji HTTP / 1.1 2 . Używa rozszerzonej sekcji BNF 2.1 tego dokumentu i opiera się zarówno na nieterminalach zdefiniowanych w tym dokumencie, jak i na innych aspektach specyfikacji HTTP / 1.1.

RFC2616, sekcja 2.1 definiuje TEKST (moje wyróżnienie ):

Reguła TEKST jest używana tylko do opisowej zawartości pól i wartości, które nie mają być interpretowane przez parser komunikatów. Słowa * TEXT MOGĄ zawierać znaki z zestawów znaków innych niż ISO-8859-1 tylko wtedy, gdy są kodowane zgodnie z zasadami RFC 2047.

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

Jest to więc zdecydowanie iso-8859-1, chyba że wykryjesz inne kodowanie zgodne z regułami RFC2047 (MIME pkt 3):

// Username: Mike
// Password T€ST
Mike:=?iso-8859-15?q?T€ST?=

W takim przypadku znak euro w słowie byłby zakodowany 0xA4zgodnie z ISO-8859-15 . Rozumiem, że należy sprawdzić te zakodowane ograniczniki słów, a następnie zdekodować zawarte w nich słowa w oparciu o określone kodowanie. Jeśli tego nie zrobisz, pomyślisz, że hasło to =?iso-8859-15?q?T¤ST?=(uwaga, 0xA4które zostanie zdekodowane, ¤gdy zostanie zinterpretowane jako iso-8859-1).

To jest moje rozumienie, nie mogę znaleźć bardziej wyraźnego potwierdzenia niż te RFC. A niektóre z nich wydają się sprzeczne. Na przykład jednym z 4 określonych celów RFC2047 (MIME, pkt 3) jest przedefiniowanie:

format wiadomości umożliwiający… tekstowe informacje w nagłówku w zestawach znaków innych niż US-ASCII.

Ale potem RFC2616 (HTTP 1.1) definiuje nagłówek przy użyciu reguły TEXT, która domyślnie jest ustawiona na iso-8859-1. Czy to oznacza, że ​​każde słowo w tym nagłówku powinno być zakodowanym słowem (tj. =?...?=Formą)?

Co więcej, żadna obecna przeglądarka tego nie robi. Używają utf-8 (Chrome, Opera), iso-8859-1 (Safari), strony kodowej systemu (IE) lub czegoś innego (jak tylko najbardziej znaczący bit z utf-8 w przypadku Firefoksa).

Edycja: właśnie zdałem sobie sprawę, że ta odpowiedź przedstawia problem bardziej z perspektywy serwera.

Michiel van Oosterhout
źródło
Kodowanie RFC 2047 nie ma zastosowania w tym przypadku.
Julian Reschke
@JulianReschke Cóż, specyfikacja wyraźnie stwierdza „tylko wtedy, gdy jest kodowana zgodnie z zasadami RFC 2047”. Rozumiem, że zasady zawarte w RFC2047 mogą nie mieć zastosowania do nagłówków HTTP, ale specyfikacja jest dość jasna w odniesieniu do niej. Dodałem, że żadna przeglądarka tak naprawdę tego nie robi.
Michiel van Oosterhout
4
specyfikacje HTTPbis nie będą już wspominać o RFC 2047.
Julian Reschke
Bardzo szczegółowy opis, dzięki @MichielvanOosterhout!
ToastyMallows
5

RFC bok, w Spring Framework , w BasicAuthenticationFilterklasie, domyślnie jest UTF-8 .

Uważam, że powodem tego wyboru jest to, że UTF-8 jest w stanie zakodować wszystkie możliwe znaki, podczas gdy ISO-8859-1 (lub ASCII) nie. Próba użycia nazwy użytkownika / hasła ze znakami nieobsługiwanymi w systemie może prowadzić do nieprawidłowego zachowania lub (co gorsza) obniżenia bezpieczeństwa.

holmis83
źródło
1
Cóż, używanie UTF-8 nie pomoże, jeśli druga strona o tym nie wie. Byłoby więc dobrze, gdyby framework Spring zaimplementował parametr charset opisany w < greenbytes.de/tech/webdav/rfc7617.html#rfc.section.2.1 >
Julian Reschke
1
@JulianReschke Poinformowałem, jak jest zaimplementowany w jednym z najpopularniejszych frameworków i prawdopodobny powód. Nie strzelaj do posłańca!
holmis83
4

Jeśli jesteś zainteresowany tym, co robią przeglądarki, gdy wpisujesz znaki inne niż ASCII w monicie logowania, właśnie spróbowałem z Firefoksem.

Wydaje się, że leniwie konwertuje to wszystko na ISO-8859-1, pobierając najmniej znaczący bajt z każdej wartości Unicode, np .:

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

Są zakodowane tak samo jak:

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

0x5a 0x3a 0x4e base64-> WjpO

anda apterus
źródło
1
Tak, to stare zachowanie Firefoksa. Został zmieniony (wydaje się, że w V57) i zamiast tego używa teraz UTF-8.
sleske
1
V59, nie V57. Obecnie w fazie testów beta.
Julian Reschke