Le RFC2617 dit d'encoder le nom d'utilisateur et le mot de passe en base64 mais ne dit pas quel codage de caractères utiliser lors de la création des octets pour l'entrée dans l'algorithme base64.
Dois-je supposer US-ASCII ou UTF8? Ou quelqu'un a-t-il déjà réglé cette question quelque part?
RFC 2617 peut être lu comme "ISO-8859-1" ou "non défini". Votre choix. Il est connu que de nombreux serveurs utilisent ISO-8859-1 (que cela plaise ou non) et échouent lorsque vous envoyez autre chose. Donc, probablement le seul choix sûr est de s'en tenir à l'ASCII.
Pour plus d'informations et une proposition pour corriger la situation, voir le projet "Un paramètre de codage pour l'authentification de base HTTP" (qui a constitué la base de la RFC 7617).
Depuis 2015, il existe RFC 7617 , qui rend le RFC 2617 obsolète. Contrairement à l'ancien RFC, le nouveau RFC définit explicitement l'encodage des caractères à utiliser pour le nom d'utilisateur et le mot de passe.
charset="UTF-8"
dans son défi, comme ceci:WWW-Authenticate: Basic realm="myChosenRealm", charset="UTF-8"
Version complète:
Lire la spécification . Si contient des détails supplémentaires, tels que la procédure de codage exacte et la liste des points de code Unicode qui doivent être pris en charge.
À partir de 2018, les navigateurs modernes seront généralement par défaut UTF-8 si un utilisateur saisit des caractères non ASCII pour le nom d'utilisateur ou le mot de passe (même si le serveur n'utilise pas le paramètre charset
).
Le paramètre realm ne prend toujours en charge que les caractères ASCII même dans la RFC 7617).
Réponse courte: iso-8859-1 sauf si des mots codés sont utilisés conformément à la RFC2047 (MIME).
Explication plus longue:
RFC2617, section 2 (Authentification HTTP) définit informations d'identification de base:
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 spécification ne doit pas être lue sans se référer à RFC2616 (HTTP 1.1) pour les définitions en BNF (comme celle ci-dessus):
Cette spécification est un complément à la spécification HTTP/1.1 2 . Il utilise la section 2.1 BNF augmentée de ce document et s'appuie à la fois sur les non-terminaux définis dans ce document et sur d'autres aspects de la spécification HTTP/1.1.
RFC2616, section 2.1 définit [~ # ~] texte [~ # ~] (accent sur le mien):
La règle TEXT n'est utilisée que pour le contenu et les valeurs des champs descriptifs qui ne sont pas destinés à être interprétés par l'analyseur de message. Les mots de * TEXT PEUVENT contenir des caractères de jeux de caractères autres que ISO-8859-1 uniquement lorsqu'ils sont codés conformément aux règles de la RFC 2047.
TEXT = <any OCTET except CTLs, but including LWS>
Il s'agit donc bien de l'iso-8859-1, sauf si vous détectez un autre codage selon les règles RFC2047 (MIME pt. 3):
// Username: Mike
// Password T€ST
Mike:=?iso-8859-15?q?T€ST?=
Dans ce cas, le signe euro dans le mot sera codé comme 0xA4
selon iso-8859-15 . Je crois comprendre que vous devez vérifier ces délimiteurs Word codés, puis décoder les mots à l'intérieur en fonction du codage spécifié. Si vous ne le faites pas, vous penserez que le mot de passe est =?iso-8859-15?q?T¤ST?=
(remarquerez que 0xA4
serait décodé en ¤
lorsqu'il est interprété comme iso-8859-1).
C'est ma compréhension, je ne peux pas trouver de confirmation plus explicite que ces RFC. Et certains semblent contradictoires. Par exemple, l'un des 4 objectifs énoncés de la RFC2047 (MIME, pt. 3) est de redéfinir:
le format des messages pour permettre ... des informations d'en-tête textuelles dans des jeux de caractères autres que US-ASCII.
Mais alors RFC2616 (HTTP 1.1) définit un en-tête en utilisant la règle TEXT qui est par défaut iso-8859-1. Cela signifie-t-il que chaque mot de cet en-tête doit être un mot codé (c'est-à-dire le =?...?=
forme)?
Également pertinent, aucun navigateur actuel ne le fait. Ils utilisent utf-8 (Chrome, Opera), iso-8859-1 (Safari), la page de codes système (IE) ou autre chose (comme seulement le bit le plus significatif d'utf-8 dans le cas de Firefox).
Edit: Je viens de réaliser que cette réponse examine le problème davantage du point de vue du serveur.
Si vous êtes intéressé par ce que font les navigateurs lorsque vous entrez des caractères non ascii à l'invite de connexion, je viens d'essayer avec Firefox.
Il semble se convertir paresseusement en ISO-8859-1 en prenant l'octet le moins significatif de chaque valeur unicode, par exemple:
User: 豚 (\u8c5a)
Password: 虎 (\u864e)
Sont codés de la même manière que:
User: Z (\u005a)
Password: N (\u004e)
0x5a 0x3a 0x4e base64-> WjpO
En dehors des RFC, dans Spring framework, la classe BasicAuthenticationFilter
, la valeur par défaut est TF-8.
Je crois que la raison de ce choix est que l'UTF-8 est capable d'encoder tous les caractères possibles, contrairement à ISO-8859-1 (ou ASCII). Essayer d'utiliser un nom d'utilisateur/mot de passe avec des caractères non pris en charge dans le système peut entraîner un comportement défectueux ou (peut-être pire) une sécurité dégradée.