2012-01-09 10 views
11

Ho uno scenario in cui devo gestire l'autenticazione delle richieste Ajax utilizzando "Autenticazione moduli". Sulla base di alcune ricerche e aiuto del mio precedente post StackOverflow, avevo deciso di utilizzare il metodo descritto allo here.Codice di risposta 401 che attiva l'autenticazione di base prima del gestore errori jquery ajax

L'idea è di inviare una risposta 401 per le richieste non autenticate e quindi gestirle nel gestore degli errori AJAX. Quindi ho un gestore di errori AJAX nella mia pagina ASP.net MVC3 Layout che reindirizza il browser alla pagina di login quando riceve 401 risposte su richieste Ajax non autenticate. Ecco il gestore degli errori di ajax.

$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) { 
    if (jqXHR.status == "401") { 
     window.location.replace(loginUrl); 
    } 
    .... 
}); 

Questo tutto funziona bene sul mio locale IIS 7.5 Server. Ma sul server in cui è ospitato il mio sito, sfortunatamente, ricevo un popup di autenticazione di base su richieste Ajax non autenticate (ad esempio la sessione scaduta), prima che il gestore di errori AJAX venga eseguito e reindirizza il browser alla pagina di accesso. Quando annullo il popup "Autenticazione richiesta" premendo il pulsante Annulla, il gestore degli errori AJAX viene quindi eseguito e vengono reindirizzati alla pagina di accesso.

Quindi, perché il browser mostra il popup di autenticazione prima di eseguire il gestore degli errori AJAX?

Edit: il server che ospita esegue IIS 6.

+0

fare attenzione seguendo il link in questo testo domanda di cui sopra "qui" ... esso segnala un'infezione trojan. – hal9000

risposta

0

tenta di rimuovere intestazione WWW-Authenticate dalla risposta.

+0

Ho provato a rimuovere l'intestazione "WWW-Authenticate" dalla risposta utilizzando response.Headers.Remove ("WWW-Authenticate") nel gestore di eventi "EndRequest" di IHttpModule, ma il codice genera [PlatformNotSupportedException: questa operazione richiede IIS modalità di pipeline integrata.]. Quindi dubito che potremmo rimuovere le intestazioni dalla risposta. – Jatin

+1

È possibile utilizzare i metodi response.Headers solo in modalità pipeline integrata IIS7, utilizzare i metodi response.ClearHeaders() e response.AppendHeader() in IIS 6 – ladoch

0

IIS 6 in modalità integrata? Non credo che ci sia qualcosa del genere, a meno che non si parli di autenticazione integrata.

La mia ipotesi è che si sta utilizzando un'estensione non-aspx, quindi su IIS6 questo significa che non sta nemmeno colpendo il processo .net. Quindi, IIS sta usando la propria pagina di risposta agli errori 401.

Probabilmente, la soluzione è forzare tutte le richieste a essere gestite dal processo .net.

L'host dovrà accedere alle proprietà IIS> configurazione> mapping di caratteri jolly e mappare tutto al processo .net.

+0

ScottE, Siamo spiacenti per le informazioni errate, infatti IIS 6 non ha la modalità pipeline integrata. Comunque, per quanto riguarda la tua ipotesi, ho un'implementazione IHttpModule, ma sta facendo quello che dovrebbe fare, cioè restituendo 401 risposte per richieste Ajax non autenticate. Non ci sono altre estensioni non-aspx per la gestione delle richieste, quindi suppongo che la richiesta venga gestita dal processo .net. Puoi trovare l'implementazione IHttpModule che sto utilizzando nel link fornito nella mia domanda. Grazie per la risposta. – Jatin

+0

No, in IIS 6, per impostazione predefinita il processo .net non gestisce gli URL senza estensione. Quindi, la richiesta non ha nemmeno colpito il tuo httpmodule. Se .net gestisce tutte le richieste, allora dovrebbe andare bene. – ScottE

+0

L'autenticazione funziona bene per le richieste non Ajax. Sto usando l'autenticazione dei moduli e se c'è una richiesta non autenticata (non-ajax), vengo reindirizzato correttamente alla Pagina di accesso. Dopo l'accesso, sono in grado di accedere a tutti i metodi di azione di asp.net MVC Controller. Il problema si verifica solo per richieste ajax non autenticate, in cui sto inviando una risposta 401 dal mio modulo.Sfortunatamente, IIS 6 sta aggiungendo due intestazioni "WWW-Authenticate" con valore "Negotiate" e "NTLM", che sta causando al browser l'attivazione del popup di autenticazione. – Jatin

0

.net non cattura gli errori 401. Quello che ho fatto è stato impostare la pagina di errore di IIS dalla pagina 401 predefinita alla mia pagina statica 401. Da quella pagina ho usato javascript per reindirizzare a un altro gestore.

1

Questa è una domanda comune con una risposta facile. il 401 viene trasformato in un 302 nella pagina di login dal modulo di autorizzazione .net. Il browser non vede mai il 401 solo il 302.

Ovviamente questo non sta funzionando bene con le chiamate Ajax.

La soluzione migliore che ho provato e che attualmente sto utilizzando riguarda la scrittura di un nuovo attributo che sta catturando 401 e lo trasformo in ... 409 che viene catturato dal gestore jquery ajax.

Fa parte di un prodotto a pagamento quindi non posso dare alcun codice.

+0

Ho già gestito la soppressione della trasformazione 401 a 302. Ma alla fine stavo ritornando a 401, e ciò sta innescando il popup di autenticazione richiesto nel browser. Oggi ho provato a restituire un codice di errore personalizzato, ad esempio 601 anziché 401 e quindi gestirlo nel gestore degli errori jjery ajax. Questo sembra funzionare sul mio server di staging, ma ci possono essere alcune insidie ​​in questo approccio? – Jatin

+1

Sì, usa 409 invece è più sicuro. 4xx sono errori di autenticazione (normalizzati). 6xx non è normalizzato. "La classe 4xx del codice di stato è intesa per i casi in cui il client sembra avere un errore." vedi http://en.wikipedia.org/wiki/List_of_HTTP_status_codes. Io uso 409 perché preferisco usare un codice di errore che esiste in quanto potrebbe non esserci supporto in alcuni browser per codici di ritorno http non esistenti. I miei test mostrano che 409 è ben supportato nei browser IE, Chrome, FF e Safari e non attiva alcuna funzione speciale del browser (302 fa). – Softlion

-1

Attendere! Pensavo avessi detto la richiesta Ajax, come puoi ottenere un popup su una richiesta Ajax? Sono abbastanza sicuro che da qualche altra parte stia attivando la chiamata all'URL anche prima della chiamata AJAX. Dal tuo scenario si è dimostrato che quando si annulla il popup, viene effettuata la richiesta effettiva di ajax e quindi è possibile eseguire un reindirizzamento ajax.

L'idea è quella di inviare una risposta 401 per le richieste non autenticate, e quindi gestire che nel gestore di errori AJAX

È possibile ottenere una risposta ajax solo se si invia una richiesta ajax, se si invia una normale richiesta http quindi otterrai un popup. Questo non ha nulla a che fare con .Net o Java :)

+3

Non so se una richiesta Ajax, che restituisce una risposta 401, debba far scattare il browser per mostrare il popup di autenticazione, ma si verifica. Sto facendo una richiesta ajax non autenticata e inviando la risposta 401, e questo fa sì che il browser visualizzi il popup "Autenticazione richiesta". Se restituisco un codice di risposta personalizzato (ad esempio 601) per la richiesta Ajax non autenticata, il browser non visualizza il popup "Authenticated Required". Tuttavia, il gestore di errori ajax viene eseguito e potrei quindi utilizzarlo per reindirizzare il browser per accedere all'URL utilizzando la normale richiesta. Questo approccio sembra funzionare – Jatin

+0

In realtà l'idea era di inviare un codice di risposta valido tramite ajax e gestirlo nel gestore di callback e nel reindirizzamento :) – Abhi

0

La soluzione here consiste nel scrivere un HttpModule personalizzato per risolvere il problema del comportamento predefinito dei framework MVC. Una volta finalmente ho potuto registrare il modulo (cheers David Ebbo) ha funzionato per me. Potresti voler scegliere i tuoi criteri per chiamare SuppressAuthenticationRedirect.

public class SuppressFormsAuthenticationRedirectModule : IHttpModule { 
    private static readonly object SuppressAuthenticationKey = new Object(); 

    public static void SuppressAuthenticationRedirect(HttpContext context) { 
    context.Items[SuppressAuthenticationKey] = true; 
    } 

    public static void SuppressAuthenticationRedirect(HttpContextBase context) { 
    context.Items[SuppressAuthenticationKey] = true; 
    } 

    public void Init(HttpApplication context) { 
    context.PostReleaseRequestState += OnPostReleaseRequestState; 
    context.EndRequest += OnEndRequest; 
    } 

    private void OnPostReleaseRequestState(object source, EventArgs args) { 
    var context = (HttpApplication)source; 
    var response = context.Response; 
    var request = context.Request; 

    if (response.StatusCode == 401 && request.Headers["X-Requested-With"] == 
     "XMLHttpRequest") { 
     SuppressAuthenticationRedirect(context.Context); 
    } 
    } 

    private void OnEndRequest(object source, EventArgs args) { 
    var context = (HttpApplication)source; 
    var response = context.Response; 

    if (context.Context.Items.Contains(SuppressAuthenticationKey)) { 
     response.TrySkipIisCustomErrors = true; 
     response.ClearContent(); 
     response.StatusCode = 401; 
     response.RedirectLocation = null; 
    } 
    } 

    public void Dispose() { 
    } 

    public static void Register() { 
    DynamicModuleUtility.RegisterModule(
     typeof(SuppressFormsAuthenticationRedirectModule)); 
    } 
} 
2

come Softlion detto

Questa è una domanda comune con una risposta facile. il 401 viene trasformato in 302 nella pagina di login> dal modulo di autorizzazione .net. Il browser non vedere mai la 401 solo il 302.

se si utilizza .NET 4 e versioni successive, è possibile utilizzare il codice qui sotto

HttpContext.Response.SuppressFormsAuthenticationRedirect = true; 

E 'un lavoro bene per me.

0

Per me questo è diventato semplice. La maggior parte dei siti Web IIS con l'autenticazione anonima hanno anche un difetto di Windows Auth abilitato

Authentication configuration

Spegnere l'autenticazione di Windows, che è quello che si apre la schermata di login quando il sito rileva il 401 anche da una chiamata AJAX.

<security> <authentication> <anonymousAuthentication enabled="true" /> <windowsAuthentication enabled="false" /> </authentication> </security>

Problemi correlati