2009-12-10 20 views
6

Abbiamo un'app ASP.NET protetta dall'autenticazione moduli. L'app utilizza pesantemente MS AJAX per chiamare i suoi servizi web.Autenticazione moduli e richieste POST da AJAX

Quando l'autenticazione dei moduli scade e viene eseguita una richiesta GET - tutto va bene (l'utente viene reindirizzato a una pagina di accesso).

MA quando i tempi di autenticazione forme fuori e un POST -request accade (Ajax) - senza redirect accade, invece le app restituisce "401 unathorized" e il browser richiede nome utente e password (non un modulo di login , ma una finestra di dialogo incorporata nei browser). Ovviamente l'inserimento di QUALSIASI username/password non aiuta mai.

Come gestirlo?

UPDATE: Dopo aver guardato con Firebug, ho appena scoperto che richieste POST regolari reindirizzare il login bene, è solo le chiamate web-service che gettano "401 Unauthorizes". La differenza tra una richiesta regolare e un servizio web è l'URL. Che è "Page.aspx" per un normale post-richiesta e "service.asmx/MethodName" per webservices ...

+1

Hai guardato con FireBug cosa viene effettivamente inviato al server e cosa ha risposto? Il prompt integrato del browser di solito indica che la risorsa a cui stai tentando di accedere è protetta dall'autenticazione di base o NTLM. Hai abilitato tale autenticazione per parti del tuo sito? –

+0

Sì, nelle impostazioni di IIS abbiamo un'autenticaiton "windows integrated" attivata (insieme a "accesso anonimo"). Grazie, proverò Firebug – Alex

risposta

2

Ok, rispondendo alla mia ricerca.

Dopo aver guardato in questo problema e la ricerca di un po 'di più ho scoperto che quando una web-app è protetto da forme-autenticazione e l'utente è non autenticato, questo è ciò che accade:

  • Se si tratta di una richiesta GET - l'utente è reindirizzato alla pagina di accesso.
  • Se si tratta di una richiesta POST a una pagina, l'utente è reindirizzato alla pagina di accesso.
  • Se si tratta di una richiesta POST-ad un web-service - l'utente ottiene 401-non autorizzate

thats come ASP.NET funziona

E se un servizio Web viene chiamato da AJAX (oggetto xmlHttpRequest) e restituisce 401, ovviamente il browser mostra una casella di accesso a comparsa.

Ora, cosa si dovrebbe fare è aggiungere del codice a Application_PostAuthenticateRequest che impedirà il lancio di 401 per i servizi web.

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) 
{ 
    if (Request.RequestType == "POST" //if its POST 
     && !User.Identity.IsAuthenticated //if user NOT authed 
     && !HasAnonymousAccess(Context) //if it's not the login page 
     ) 
    { 
     //lets get the auth type 
     Configuration config = WebConfigurationManager.OpenWebConfiguration("~"); 
     SystemWebSectionGroup grp = (SystemWebSectionGroup)config.GetSectionGroup("system.web"); 
     AuthenticationSection auth = grp.Authentication; 
     //if it FORMS auth 
     if(auth.Mode== AuthenticationMode.Forms) 
     { 

      //then redirect... this redirect won't work for AJAX cause xmlHttpRequest can't handle redirects, but anyway... 
      Response.Redirect(FormsAuthentication.LoginUrl, true); 
      Response.End(); 

     } 
    } 
} 
public static bool HasAnonymousAccess(HttpContext context) 
{ 
    return UrlAuthorizationModule.CheckUrlAccessForPrincipal(
     context.Request.Path, 
     new GenericPrincipal(new GenericIdentity(string.Empty), null), 
     context.Request.HttpMethod); 
} 
+0

@jazbit, puoi indicare una certa persecuzione che parla del codice di stato 401 per i servizi web, ho uno scenario in cui sto verificando la sessione ecpiry e sto facendo un reindirizzamento che risulta 401 al client –

+0

Response.End è tipicamente un brutta cosa da fare Di solito vuoi 'response.Redirect (url, False); HttpContext.Current.ApplicationInstance.CompleteRequest(); ' –

1

Vedo due soluzioni:

(1) meccanismo di "Heart Beat". Su ogni pagina includere uno script che verrà "ping" del server da qualche richiesta AJAX fittizio, come:

<script> 
    setInterval(ping, 60000); // based on comment by John 
    function ping() 
    { 
     $.get('/do/nothing'); 
    } 
</script> 

In questo modo la sessione non dovrebbe scadere fino a quando la finestra del browser è aperto.

(2) Su ogni richiesta Ajax controllare lo stato della risposta. Se la risposta ha il codice "401 non autorizzato" (o qualsiasi altro codice diverso da 200), ciò significa che la sessione è scaduta e invece di caricare la risposta in una finestra di dialogo nella pagina reindirizzare l'utente alla pagina di accesso.

Conclusione sulla base di commenti:

La soluzione migliore sarebbe quella di combinare i due meccanismi di cui sopra. Il meccanismo del battito cardiaco aiuterà a mantenere viva la sessione finché la pagina viene visualizzata nel browser. Ma non lo garantisce di sicuro. La connessione al server può essere interrotta e riaperta quando la sessione è scaduta. Quindi dovresti comunque controllare lo stato della risposta.

+0

puoi fare solo 'setInterval (ping, 60000);' passare una stringa a setInterval non è raccomandato in quanto è l'equivalente di eval() –

+0

Dovrai anche chiamare di nuovo setInterval all'interno di ping() se vuoi che venga eseguito più di una volta –

+0

Qualsiasi altro codice di 200 non significa che la sessione è scaduta. –

Problemi correlati