¿Qué codificación debo usar para la autenticación básica HTTP?


Respuestas:


72

Especificaciones originales - RFC 2617

RFC 2617 se puede leer como "ISO-8859-1" o "indefinido". Tu elección. Se sabe que muchos servidores usan ISO-8859-1 (te guste o no) y fallarán cuando envíes algo más. Así que probablemente la única opción segura sea ceñirse a ASCII.

Para obtener más información y una propuesta para solucionar la situación, consulte el borrador "Un parámetro de codificación para la autenticación básica HTTP" (que formó la base de RFC 7617).

Nuevo - RFC 7617

Desde 2015 existe el RFC 7617 , que deja obsoleto el RFC 2617. A diferencia del antiguo RFC, el nuevo RFC define explícitamente la codificación de caracteres que se utilizará para el nombre de usuario y la contraseña.

  • La codificación predeterminada aún no está definida. Solo se requiere que sea compatible con US-ASCII (lo que significa que asigna bytes ASCII a bytes ASCII, como lo hace UTF-8).
  • El servidor puede enviar opcionalmente un parámetro de autenticación adicional charset="UTF-8"en su desafío, como este:
    WWW-Authenticate: Basic realm="myChosenRealm", charset="UTF-8"
    Esto anuncia que el servidor aceptará caracteres no ASCII en el nombre de usuario / contraseña, y que espera que estén codificados en UTF-8 (específicamente Normalization Form C) . Tenga en cuenta que solo se permite UTF-8.

Versión completa:

Lea la especificación . Si contiene detalles adicionales, como el procedimiento de codificación exacto y la lista de puntos de código Unicode que deben admitirse.

Soporte de navegador

A partir de 2018, los navegadores modernos generalmente usarán UTF-8 de forma predeterminada si un usuario ingresa caracteres no ASCII para el nombre de usuario o la contraseña (incluso si el servidor no usa el charsetparámetro).

  • Chrome también parece usar UTF-8
  • Internet Explorer no usa UTF-8 ( problema # 11879588 )
  • Firefox está experimentando con un cambio planeado actualmente para v59 ( error 1419658 )

Reino

El parámetro de reino todavía solo admite caracteres ASCII incluso en RFC 7617.


Gracias Julian. Me encontré con esa propuesta, pero parece que ha expirado y no he ido más lejos. Lástima :-(.
— Dobes Vandermeer

1
Tu respuesta debe ser la mejor. Puedo parafrasearlo como ASCII con seguridad, tal vez ISO-8859-1 si tienes suerte.
— Dobes Vandermeer

Parece que la última versión 04 de la propuesta (que coincidentemente parece ser publicada hoy) vence el 1 de agosto de 2012.
— Michiel van Oosterhout

La respuesta era obsoleta, ya que no mencionaba RFC 7617. Edité para incluir esto. Julian: Espero que no te importe.
— sleske

Vaya, me acabo de dar cuenta de que en realidad eres el autor de RFC 7617. Ahora realmente espero no haber editado mal algo.
— sleske

41

Respuesta corta: iso-8859-1 a menos que se utilicen palabras codificadas de acuerdo con RFC2047 (MIME).

Explicación más larga:

RFC2617, sección 2 (Autenticación HTTP) define las credenciales básicas :

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

La especificación no debe leerse sin consultar RFC2616 (HTTP 1.1) para obtener definiciones en BNF (como la anterior):

Esta especificación es un complemento de la especificación HTTP / 1.1 2 . Utiliza la sección 2.1 de BNF aumentada de ese documento y se basa tanto en los no terminales definidos en ese documento como en otros aspectos de la especificación HTTP / 1.1.

RFC2616, sección 2.1 define TEXTO (énfasis mío):

La regla TEXT solo se utiliza para valores y contenidos de campos descriptivos que no están destinados a ser interpretados por el analizador de mensajes. Las palabras * TEXT PUEDEN contener caracteres de conjuntos de caracteres distintos de ISO-8859-1 solo cuando se codifican de acuerdo con las reglas de RFC 2047.

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

Entonces, definitivamente es iso-8859-1 a menos que detecte alguna otra codificación de acuerdo con las reglas RFC2047 (MIME pt. 3):

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

En este caso, el signo del euro en la palabra se codificaría 0xA4según iso-8859-15 . Tengo entendido que debe verificar estos delimitadores de palabras codificadas y luego decodificar las palabras internas según la codificación especificada. Si no lo hace, pensará que la contraseña es =?iso-8859-15?q?T¤ST?=(observe que 0xA4se decodificará ¤cuando se interprete como iso-8859-1).

Este es mi entendimiento, no puedo encontrar una confirmación más explícita que estas RFC. Y algo de eso parece contradictorio. Por ejemplo, uno de los 4 objetivos declarados de RFC2047 (MIME, punto 3) es redefinir:

el formato de los mensajes para permitir ... información de encabezado textual en juegos de caracteres que no sean US-ASCII.

Pero luego RFC2616 (HTTP 1.1) define un encabezado usando la regla TEXT que por defecto es iso-8859-1. ¿Significa eso que cada palabra en este encabezado debe ser una palabra codificada (es decir, la =?...?=forma)?

También es relevante, ningún navegador actual hace esto. Usan utf-8 (Chrome, Opera), iso-8859-1 (Safari), la página de códigos del sistema (IE) o algo más (como solo el bit más significativo de utf-8 en el caso de Firefox).

Editar: Me acabo de dar cuenta de que esta respuesta analiza el problema más desde la perspectiva del lado del servidor.


La codificación RFC 2047 no se aplica en este caso.
— Julian Reschke

@JulianReschke Bueno, la especificación establece claramente "solo cuando se codifica de acuerdo con las reglas de RFC 2047". Entiendo que las reglas en RFC2047 pueden no ser aplicables a los encabezados HTTP, pero la especificación es bastante clara al referirse a ellas. He añadido el hecho de que ningún navegador hace esto.
— Michiel van Oosterhout

4
las especificaciones HTTPbis ya no mencionarán RFC 2047.
— Julian Reschke

Escrito muy detallado, ¡gracias @MichielvanOosterhout!
— ToastyMallows

5

Dejando a un lado las RFC, en Spring Framework , la BasicAuthenticationFilterclase, el valor predeterminado es UTF-8 .

Creo que la razón de esta elección es que UTF-8 es capaz de codificar todos los caracteres posibles, mientras que ISO-8859-1 (o ASCII) no lo es. Intentar utilizar un nombre de usuario / contraseña con caracteres no admitidos en el sistema puede provocar un comportamiento defectuoso o (quizás peor) una seguridad degradada.


1
Bueno, usar UTF-8 no ayuda si la otra parte no lo sabe. Por lo tanto, sería bueno si el marco de Spring implementara el parámetro de juego de caracteres descrito en < greenbytes.de/tech/webdav/rfc7617.html#rfc.section.2.1 >
— Julian Reschke

1
@JulianReschke Informé cómo se implementa en uno de los marcos más comunes y una probable razón para ello. ¡No dispares al mensajero!
— holmis83

4

Si está interesado en lo que hacen los navegadores cuando ingresa caracteres no ascii en el indicador de inicio de sesión, acabo de probar con Firefox.

Parece convertir perezosamente todo a ISO-8859-1 tomando el byte menos significativo de cada valor Unicode, por ejemplo:

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

Están codificados de la misma manera que:

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

0x5a 0x3a 0x4e base64-> WjpO


1
Sí, ese es el antiguo comportamiento de Firefox. Se cambió (en V57, al parecer) y ahora usa UTF-8 en su lugar.
— sleske

1
V59, no V57. Actualmente en prueba beta.
— Julian Reschke
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.