2009-12-10 16 views
6

Wir haben eine ASP.NET App durch Formularauthentifizierung geschützt. Die App nutzt MS AJAX stark zum Aufruf ihrer Web-Dienste.Formulare Authentifizierung und POST-Anfragen von AJAX

Wenn die Formularauthentifizierung abgelaufen ist und eine Anforderung GET auftritt, ist alles in Ordnung (der Benutzer wird auf eine Anmeldeseite umgeleitet).

ABER, wenn die Formularauthentifizierung Zeiten und ein POST -request passiert (Ajax) - keine Umleitung erfolgt stattdessen die App gibt „401 unbefugte“ und den Browser fragt nach Benutzername und Passwort (kein Login-Formular , aber ein Browser eingebauten Dialog). Natürlich hilft die Eingabe von Benutzername/Passwort nie.

Wie gehe ich damit um?

UPDATE: Nach dem Suchen mit Firebug, habe ich gerade herausgefunden, dass regelmäßige POST-Anfragen umleiten, um sich gut einzuloggen, ist es nur Web-Service-Anrufe, die "401 Unauthorizes" werfen. Der Unterschied zwischen einer regulären Anfrage und einem Web-Service ist URL. Welches ist "page.aspx" für eine regelmäßige Post Anfrage und "Service.asmx/Method" für einen Web Service ...

+1

Haben Sie mit FireBug nachgesehen, was tatsächlich an den Server gesendet wurde und was es zurückgeschickt hat? Die integrierte Eingabeaufforderung des Browsers bedeutet normalerweise, dass die Ressource, auf die Sie zugreifen möchten, durch die Basis- oder NTLM-Authentifizierung geschützt ist. Ist diese Authentifizierung für Teile Ihrer Website aktiviert? –

+0

Ja, in IIS-Einstellungen haben wir "Windows integrierte" Authentifizierung (zusammen mit "anonymen Zugriff"). Danke, ich werde versuchen Firebug – Alex

Antwort

2

Ok, beantworte meine eigene Frage.

Nach in diesem Thema suchen und ein bisschen mehr Erforschung fand ich, dass, wenn eine Web-App von Forms-Authentifizierung geschützt ist und der Benutzer ist nicht authentifiziert, das ist, was passiert:

  • Wenn es eine GET-Anfrage - der Benutzer wird auf die Anmeldeseite umgeleitet.
  • Wenn es eine POST-Anfrage an eine Seite ist - der Benutzer ist umgeleitet auf die Anmeldeseite.
  • Wenn es eine POST-Anfrage an einen Web-Service - die Benutzer erhalten 401-unbefugten

Das ist, wie ASP.NET funktioniert

Und wenn ein Web-Service von AJAX (xmlHttpRequest Objekt) aufgerufen wird und 401 zurückgibt - natürlich zeigt der Browser eine Popup-Login-Box.

Nun, was Sie tun sollten, ist fügen Sie einen Code zu Application_PostAuthenticateRequest, die 401 für Webservices verhindern zu verhindern.

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, können Sie auf einige Doucmentation, die über die 401-Status-Code für Web-Services spricht, habe ich ein Szenario, wo ich für Sitzung ecpiry und bin eine Umleitung, die Ergebnisse 401 an den Client –

+0

Response.End ist in der Regel ein schlechte Sache zu tun. Normalerweise wollen Sie 'response.Redirect (url, False); HttpContext.Current.ApplicationInstance.CompleteRequest(); ' –

1

Ich sehe zwei Lösungen:

(1) "Heart Beat" -Mechanismus. Auf jeder Seite ist ein Skript, das der Server „ping“ durch eine Dummy-Ajax-Anforderung wird, wie:

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

diese Weise wird die Sitzung nicht so lange, wie die Browser-Fenster geöffnet sind ablaufen soll.

(2) Überprüfen Sie bei jeder Ajax-Anfrage den Status der Antwort. Wenn die Antwort den Code "401 unauthorized" (oder einen anderen Code, der 200 ist) hat, bedeutet dies, dass die Sitzung abgelaufen ist und anstatt die Antwort in einige Dialogfelder auf der Seite zu laden, wird der Benutzer zur Anmeldeseite umgeleitet.

Schlussfolgerung basierend auf Kommentare:

Die beste Lösung, die beiden oben genannten Mechanismen zu kombinieren wäre. Der Heartbeat-Mechanismus hilft dabei, die Sitzung am Leben zu halten, solange die Seite im Browser angezeigt wird. Aber das garantiert das nicht. Die Verbindung zum Server kann abgebrochen und nach Ablauf der Sitzung wieder geöffnet werden. Daher sollten Sie den Antwortstatus trotzdem überprüfen.

+0

Sie können nur 'setInterval (ping, 60000);' eine Zeichenfolge an setInterval übergeben wird nicht empfohlen, da es das Äquivalent von eval() ist –

+0

Sie müssen SetInterval auch wieder innerhalb ping() aufrufen Wenn Sie möchten, dass es mehr als einmal ausgeführt wird –

+0

Jeder andere Code als 200 bedeutet nicht, dass die Sitzung abgelaufen ist. –

Verwandte Themen