2009-12-10 4 views
6

Nous avons une application ASP.NET protégée par l'authentification par formulaires. L'application utilise massivement MS AJAX pour appeler ses services Web.Formulaires Authentification et requêtes POST d'AJAX

Lorsque l'authentification des formulaires arrive à expiration et qu'une requête GET se produit, tout va bien (l'utilisateur est redirigé vers une page de connexion).

MAIS lorsque les formulaires temps d'authentification hors et un POST -request arrive (ajax) - pas redirect cela arrive, au lieu des retours d'applications « 401 unathorized » et le navigateur vous invite à entrer le nom d'utilisateur et mot de passe (non un formulaire de connexion , mais un navigateur intégré dans les navigateurs). Bien sûr, entrer n'importe quel nom d'utilisateur/mot de passe n'aide jamais.

Comment puis-je gérer cela? Après avoir regardé avec firebug, je viens de découvrir que les requêtes POST normales redirigent vers la connexion, ce sont seulement les appels de service web qui lancent "401 Unauthorizes". La différence entre une requête régulière et un service Web est une URL. Ce qui est "page.aspx" pour un post-demande régulière et "Service.asmx/NomMéthode" pour webservices ...

+1

Avez-vous regardé avec FireBug ce qui est réellement envoyé au serveur et ce qu'il a répondu? L'invite intégrée du navigateur signifie généralement que la ressource à laquelle vous essayez d'accéder est protégée par une authentification de base ou NTLM. Avez-vous une telle authentification activée pour certaines parties de votre site? –

+0

Oui, dans les paramètres IIS, nous avons "windows integrated" authenticaiton (avec "accès anonyme"). Merci, je vais essayer Firebug – Alex

Répondre

2

Ok, répondre à mes questions.

Après avoir examiné cette question et faire des recherches un peu plus je trouve que quand une application Web est protégé par les formulaires d'authentification et l'utilisateur est non authentifié, voici ce qui se passe:

  • Si c'est une requête GET - l'utilisateur est redirigé vers la page de connexion.
  • S'il s'agit d'une demande POST à ​​une page - l'utilisateur est redirigé vers la page de connexion.
  • Si c'est un POST-demande à un service Web - l'utilisateur obtient 401-
  • non autorisés

C'est comment ASP.NET Works

Et si un service Web est appelé par AJAX (objet xmlHttpRequest) et renvoie 401 - bien sûr, le navigateur affiche une boîte de connexion pop-up.

Maintenant, ce que vous devez faire est d'ajouter du code à Application_PostAuthenticateRequest qui empêchera de lancer 401 pour les services 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, pouvez-vous pointer vers une doucmentation qui parle du code d'état 401 pour les services Web, j'ai un scénario où je vérifie l'ecpiry de session et je fais une redirection qui résulte 401 au client –

+0

Response.End est généralement un mauvaise chose à faire. Habituellement, vous voulez 'response.Redirect (url, False); HttpContext.Current.ApplicationInstance.CompleteRequest(); ' –

1

Je vois deux solutions: mécanisme

(1) "battement de coeur". Sur chaque page comprend un script qui « ping » le serveur par une requête ajax factice, comme:

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

De cette façon, la session ne devrait pas expirer tant que la fenêtre du navigateur est ouvert. (2) Sur chaque requête ajax, vérifiez l'état de la réponse. Si la réponse a le code "401 non autorisé" (ou tout autre code différent de 200), cela signifie que la session a expiré et au lieu de charger la réponse dans une boîte de dialogue dans la page rediriger l'utilisateur vers la page de connexion.

Conclusion basée sur les commentaires:

La meilleure solution serait de combiner les deux mécanismes ci-dessus. Le mécanisme Heartbeat permet de maintenir la session active tant que la page est affichée dans le navigateur. Mais dans ne garantit pas cela à coup sûr. La connexion au serveur peut être rompue et rouverte lorsque la session a expiré. Donc, vous devriez vérifier le statut de la réponse de toute façon.

+0

vous pouvez faire juste 'setInterval (ping, 60000);' passer une chaîne à setInterval n'est pas recommandé car c'est l'équivalent de eval() –

+0

Vous devrez également rappeler setInterval dans ping() si vous voulez qu'il s'exécute plus d'une fois –

+0

Tout autre code que 200 ne signifie pas que la session a expiré. –

Questions connexes