Quale codifica devo usare per l'autenticazione di base HTTP?


Risposte:


74

Specifiche originali - RFC 2617

RFC 2617 può essere letto come "ISO-8859-1" o "non definito". La tua scelta. È noto che molti server usano ISO-8859-1 (piaccia o no) e falliranno quando invii qualcos'altro. Quindi probabilmente l'unica scelta sicura è attenersi all'ASCII.

Per ulteriori informazioni e una proposta per risolvere la situazione, vedere la bozza "Un parametro di codifica per l'autenticazione di base HTTP" (che ha costituito la base per RFC 7617).

Nuovo - RFC 7617

Dal 2015 esiste la RFC 7617 , che rende obsoleta la RFC 2617. A differenza della vecchia RFC, la nuova RFC definisce esplicitamente la codifica dei caratteri da utilizzare per nome utente e password.

  • La codifica predefinita è ancora indefinita. È richiesto solo per essere compatibile con US-ASCII (il che significa che mappa i byte ASCII in byte ASCII, come fa UTF-8).
  • Il server può facoltativamente inviare un parametro di autenticazione aggiuntivo charset="UTF-8"nella sua sfida, come questo:
    WWW-Authenticate: Basic realm="myChosenRealm", charset="UTF-8"
    questo annuncia che il server accetterà caratteri non ASCII in nome utente / password e che si aspetta che siano codificati in UTF-8 (in particolare Modulo di normalizzazione C) . Nota che è consentito solo UTF-8.

Versione completa:

Leggi le specifiche . Se contiene dettagli aggiuntivi, come la procedura di codifica esatta e l'elenco dei punti di codice Unicode che dovrebbero essere supportati.

Supporto del browser

A partire dal 2018, i browser moderni di solito utilizzano UTF-8 per impostazione predefinita se un utente immette caratteri non ASCII per nome utente o password (anche se il server non utilizza il charsetparametro).

  • Anche Chrome sembra utilizzare UTF-8
  • Internet Explorer non utilizza UTF-8 ( problema # 11879588 )
  • Firefox sta sperimentando una modifica attualmente pianificata per la v59 ( bug 1419658 )

Regno

Il parametro realm supporta ancora solo i caratteri ASCII anche in RFC 7617.


Grazie Julian. Mi ero imbattuto in quella proposta ma sembra che sia scaduta e non sia andata oltre. Peccato :-(.
Dobes Vandermeer

1
La tua risposta deve essere la migliore. Posso parafrasarlo come ASCII di sicuro, forse ISO-8859-1 se sei fortunato.
Dobes Vandermeer

Sembra che l' ultima versione 04 della proposta (che guarda caso sia stata pubblicata oggi) scade il 1 ° agosto 2012.
Michiel van Oosterhout

La risposta era obsoleta, poiché non menzionava la RFC 7617. Ho modificato per includerla. Julian: Spero non ti dispiaccia.
sleske

Oops - Mi sono appena reso conto che sei l'autore dell'RFC 7617. Ora spero davvero di non aver modificato male qualcosa.
sleske

41

Risposta breve: iso-8859-1 a meno che non vengano utilizzate parole codificate in conformità con RFC2047 (MIME).

Spiegazione più lunga:

RFC2617, sezione 2 (autenticazione HTTP) definisce le credenziali di 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 specifica non deve essere letta senza fare riferimento a RFC2616 (HTTP 1.1) per le definizioni in BNF (come quella sopra):

Questa specifica è complementare alla specifica HTTP / 1.1 2 . Utilizza la sezione 2.1 BNF aumentata di quel documento e si basa su entrambi i non terminali definiti in quel documento e su altri aspetti della specifica HTTP / 1.1.

RFC2616, sezione 2.1 definisce TEXT (enfasi mia):

La regola TEXT viene utilizzata solo per i contenuti e i valori dei campi descrittivi che non devono essere interpretati dal parser del messaggio. Le parole di * TEXT POSSONO contenere caratteri di set di caratteri diversi da ISO-8859-1 solo se codificati secondo le regole dell'RFC 2047.

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

Quindi è sicuramente iso-8859-1 a meno che non si rilevi qualche altra codifica secondo le regole RFC2047 (MIME pt.3 ):

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

In questo caso il segno dell'euro nella parola sarebbe codificato come 0xA4 secondo iso-8859-15 . A quanto mi risulta, dovresti controllare questi delimitatori di parole codificati e quindi decodificare le parole all'interno in base alla codifica specificata. Se non lo fai, penserai che la password sia =?iso-8859-15?q?T¤ST?=(nota che 0xA4verrebbe decodificata ¤se interpretata come iso-8859-1).

Questa è la mia comprensione, non riesco a trovare una conferma più esplicita di queste RFC. E alcuni sembrano contraddittori. Ad esempio, uno dei 4 obiettivi dichiarati di RFC2047 (MIME, pt.3) è ridefinire:

il formato dei messaggi per consentire ... informazioni di intestazione testuali in set di caratteri diversi da US-ASCII.

Ma poi RFC2616 (HTTP 1.1) definisce un'intestazione utilizzando la regola TEXT che per impostazione predefinita è iso-8859-1. Ciò significa che ogni parola in questa intestazione dovrebbe essere una parola codificata (cioè la =?...?=forma)?

Anche rilevante, nessun browser corrente lo fa. Usano utf-8 (Chrome, Opera), iso-8859-1 (Safari), la code page di sistema (IE) o qualcos'altro (come solo il bit più significativo di utf-8 nel caso di Firefox).

Modifica: mi sono appena reso conto che questa risposta esamina il problema più dal punto di vista del lato server.


La codifica RFC 2047 non si applica in questo caso.
Julian Reschke

@ JulianReschke Bene, la specifica afferma chiaramente "solo se codificata secondo le regole della RFC 2047". Capisco che le regole in RFC2047 potrebbero non essere applicabili alle intestazioni HTTP, ma la specifica è abbastanza chiara in riferimento ad essa. Ho aggiunto il fatto che nessun browser lo fa effettivamente.
Michiel van Oosterhout

4
le specifiche HTTPbis non menzioneranno più la RFC 2047.
Julian Reschke

Resoconto molto dettagliato, grazie @MichielvanOosterhout!
ToastyMallows

5

RFC a parte, nel framework Spring , la BasicAuthenticationFilterclasse, l'impostazione predefinita è UTF-8 .

Il motivo di questa scelta credo sia che UTF-8 sia in grado di codificare tutti i caratteri possibili, mentre ISO-8859-1 (o ASCII) non lo è. Cercare di utilizzare nome utente / password con caratteri non supportati nel sistema può portare a comportamenti non corretti o (forse peggio) a un degrado della sicurezza.


1
Bene, l'uso di UTF-8 non aiuta se l'altra parte non lo sa. Quindi sarebbe bello se il framework Spring implementasse il parametro charset descritto in < greenbytes.de/tech/webdav/rfc7617.html#rfc.section.2.1 >
Julian Reschke

1
@JulianReschke ho informato su come è implementato in uno dei framework più comuni e una probabile ragione per questo. Non sparare al messaggero!
holmis83

4

Se sei interessato a cosa fanno i browser quando inserisci caratteri non ASCII al prompt di accesso, ho appena provato con Firefox.

Sembra convertire pigramente tutto in ISO-8859-1 prendendo il byte meno significativo di ogni valore Unicode, ad esempio:

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

Sono codificati come:

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

0x5a 0x3a 0x4e base64-> WjpO


1
Sì, questo è il vecchio comportamento in Firefox. È stato modificato (nella V57, a quanto pare) e ora utilizza UTF-8.
sleske

1
V59, non V57. Attualmente in beta test.
Julian Reschke
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.