Come posso sopprimere la finestra di autenticazione del browser?

La mia applicazione web ha una pagina di accesso che invia le credenziali di autenticazione tramite una chiamata AJAX. Se l’utente immette il nome utente e la password corretti, tutto va bene, ma in caso contrario, accade quanto segue:

  1. Il server Web determina che sebbene la richiesta includesse un’intestazione Autorizzazione ben formata, le credenziali nell’intestazione non si autenticano correttamente.
  2. Il server Web restituisce un codice di stato 401 e include una o più intestazioni Autenticazione WWW che elencano i tipi di autenticazione supportati.
  3. Il browser rileva che la risposta alla mia chiamata sull’object XMLHttpRequest è una 401 e la risposta include intestazioni Autenticazione WWW. Quindi apre una finestra di autenticazione chiedendo, ancora, il nome utente e la password.

Tutto ciò va bene fino al passaggio 3. Non voglio che la finestra di dialogo compaia, voglio gestire la risposta 401 nella mia funzione di callback AJAX. (Ad esempio, visualizzando un messaggio di errore nella pagina di accesso.) Voglio che l’utente reinserisca il nome utente e la password, ovviamente, ma voglio che vedano il mio amichevole, rassicurante modulo di login, non il brutto browser, predefinito finestra di autenticazione

Per inciso, non ho alcun controllo sul server, quindi averlo restituire un codice di stato personalizzato (cioè qualcosa di diverso da un 401) non è un’opzione.

C’è un modo per sopprimere la finestra di autenticazione? In particolare, posso sopprimere la finestra di dialogo Richiesta autenticazione in Firefox 2 o versioni successive? C’è un modo per sopprimere la finestra di dialogo Connetti a [host] in IE 6 e versioni successive?


modificare
Ulteriori informazioni dall’autore (18 settembre):
Devo aggiungere che il vero problema con la finestra di dialogo di autenticazione del browser è che non fornisce informazioni sufficienti all’utente.

    L’utente ha appena inserito un nome utente e una password tramite il modulo nella pagina di accesso, ritiene di averli digitati entrambi correttamente e ha fatto clic sul pulsante Invia o su Invio. La sua aspettativa è che sarà portato alla pagina successiva o forse ha detto che ha inserito le sue informazioni in modo errato e dovrebbe riprovare. Tuttavia, viene presentato con una finestra di dialogo inaspettata.

    La finestra di dialogo non riconosce il fatto che ha appena inserito un nome utente e una password. Non indica chiaramente che c’era un problema e che avrebbe dovuto riprovare. Invece, la finestra di dialogo presenta all’utente informazioni criptiche come “Il sito dice: ‘ [realm] ‘.” Dove [regno] è un nome di regno breve che solo un programmatore potrebbe amare.

    I progettisti di Web broswer prendono nota: nessuno chiederebbe come sopprimere la finestra di autenticazione se la finestra di dialogo fosse semplicemente più user-friendly. L’ intera ragione per cui sto facendo un modulo di accesso è che il nostro team di gestione dei prodotti considera giustamente le windows di autenticazione dei browser.

    Non penso che sia ansible: se si utilizza l’implementazione del client HTTP del browser, verrà sempre visualizzata tale finestra di dialogo. Mi vengono in mente due hack:

    1. Forse Flash lo gestisce in modo diverso (non l’ho ancora provato), quindi avere un filmato flash potrebbe rendere la richiesta utile.

    2. È ansible impostare un ‘proxy’ per il servizio a cui si sta accedendo sul proprio server e modificare leggermente le intestazioni di autenticazione, in modo che il browser non le riconosca.

    Ho riscontrato lo stesso problema qui e l’ingegnere di backend della mia azienda ha implementato un comportamento apparentemente considerato una buona pratica: quando una chiamata a un URL restituisce un 401, se il client ha impostato l’intestazione X-Requested-With: XMLHttpRequest , il server rilascia l’intestazione www-authenticate nella sua risposta.

    L’effetto collaterale è che il popup di autenticazione predefinito non appare.

    Assicurati che la tua chiamata API abbia l’intestazione X-Requested-With impostata su XMLHttpRequest . Se è così, non c’è niente da fare se non cambiare il comportamento del server in base a questa buona pratica …

    Il browser visualizza una richiesta di accesso quando sono soddisfatte entrambe le seguenti condizioni:

    1. Lo stato HTTP è 4xx
    2. WWW-Authenticate intestazione WWW-Authenticate è presente nella risposta

    Se è ansible controllare la risposta HTTP, è ansible rimuovere l’intestazione WWW-Authenticate dalla risposta e il browser non farà apparire la finestra di dialogo di accesso.

    Se non è ansible controllare la risposta, è ansible impostare un proxy per filtrare l’intestazione WWW-Authenticate dalla risposta.

    Per quanto ne so (sentiti libero di correggermi se ho torto), non c’è modo di impedire il prompt di login una volta che il browser riceve l’intestazione WWW-Authenticate .

    Mi rendo conto che questa domanda e le sue risposte sono molto vecchie. Ma sono finito qui. Forse anche gli altri lo faranno.

    Se si ha accesso al codice per il servizio Web che restituisce il 401. Basta cambiare il servizio per restituire un 403 (Proibito) in questa situazione invece 401. Il browser non richiederà le credenziali in risposta a un 403. 403 è il codice corretto per un utente autenticato che non è autorizzato per una risorsa specifica. Quale sembra essere la situazione del PO.

    Dal documento IETF su 403:

    Un server che riceve credenziali valide non adeguate per l’accesso dovrebbe rispondere con il codice di stato 403 (Proibito)

    In Mozilla puoi ottenerlo con il seguente script quando crei l’object XMLHttpRequest:

     xmlHttp=new XMLHttpRequest(); xmlHttp.mozBackgroundRequest = true; xmlHttp.open("GET",URL,true,USERNAME,PASSWORD); xmlHttp.send(null); 

    La seconda linea impedisce la finestra di dialogo ….

    Quale tecnologia server usi e c’è un particolare prodotto che usi per l’autenticazione?

    Dal momento che il browser sta facendo il suo lavoro, credo che sia necessario modificare le cose sul lato server per non restituire un codice di stato 401. Questo può essere fatto utilizzando moduli di autenticazione personalizzati che restituiscono semplicemente il modulo nuovamente quando l’autenticazione fallisce.

    In Mozilla land, l’impostazione del parametro mozBackgroundRequest di XMLHttpRequest ( docs ) su true elimina le windows di dialogo e fa fallire semplicemente le richieste. Tuttavia, non so quanto sia valido il supporto cross-browser (incluso se la qualità delle informazioni di errore su quelle richieste non riuscite è molto buona tra i vari browser.)

    jan.vdbergh ha la verità, se è ansible modificare il 401 sul lato server per un altro codice di stato, il browser non cattura e dipinge il pop-up. Un’altra soluzione potrebbe essere modificare l’intestazione WWW-Authenticate per un’altra intestazione personalizzata. Non credo perché il diverso browser non può supportarlo, in alcune versioni di Firefox possiamo fare la richiesta xhr con mozBackgroundRequest, ma negli altri browser ?? qui, c’è un link interessante con questo problema in Chromium.

    Ho lo stesso problema con MVC 5 e VPN, dove ogni volta che ci troviamo fuori dalla DMZ utilizzando la VPN, ci troviamo a dover rispondere a questo messaggio del browser. Usando .net Semplicemente gestisco il routing dell’errore usando

        

    finora ha funzionato perché l’azione Index sotto il controller di casa convalida l’utente. La vista in questa azione, se l’accesso non è riuscito, dispone di controlli di accesso che utilizzo per registrare l’utente utilizzando la query LDAP passata in Directory Services:

      DirectoryEntry entry = new DirectoryEntry("LDAP://OurDomain"); DirectorySearcher Dsearch = new DirectorySearcher(entry); Dsearch.Filter = "(SAMAccountName=" + UserID + ")"; Dsearch.PropertiesToLoad.Add("cn"); 

    Anche se questo ha funzionato fino ad ora, e devo farti sapere che sto ancora testandolo e il codice sopra non ha avuto motivo di correre quindi è sobject alla rimozione … il testing include attualmente il tentativo di scoprire un caso in cui il secondo set di codice è di ulteriore utilità. Ancora una volta, questo è un work in progress, ma dal momento che potrebbe essere di qualche aiuto o dare uno scherzo al tuo cervello per alcune idee, ho deciso di aggiungerlo ora … Lo aggiornerò con i risultati finali una volta che tutti i test sono stati eseguiti.

    Per coloro che non hanno C # ecco ActionAttribute che restituisce 400 invece di 401 , e la finestra di dialogo di autenticazione di base “inghiotte”.

     public class NoBasicAuthDialogAuthorizeAttribute : AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { base.HandleUnauthorizedRequest(filterContext); filterContext.Result = new HttpStatusCodeResult(400); } } 

    usare come segue:

     [NoBasicAuthDialogAuthorize(Roles = "A-Team")] public ActionResult CarType() { // your code goes here } 

    Spero che questo ti salvi un po ‘di tempo.

    Sto usando Node, Express e Passport e stavo lottando con lo stesso problema. L’ho fatto funzionare impostando esplicitamente l’intestazione www-authenticate su una stringa vuota. Nel mio caso, assomigliava a questo:

     (err, req, res, next) => { if (err) { res._headers['www-authenticate'] = '' return res.json(err) } } 

    Spero che aiuti qualcuno!