2009-05-15 6 views
5

Lors de la construction d'un système de gestion de contenu intégrant jquery ajax dans son interface graphique, j'ai rencontré un obstacle. Il semble que certains clients passent trop de temps à réfléchir à ce qu'ils vont écrire et donc la session du serveur les déconnecte, étant naturellement le web ils n'ont aucune idée à ce sujet. Lorsqu'ils tentent de soumettre les modifications, j'utilise un appel ajax sur le serveur pour enregistrer les données. Ce que je m'attendrais à ce que se produise ensuite, c'est que l'application du serveur MVC retournera un statut "401 Non autorisé". Je pourrais alors obtenir mon objet jquery ajax pour demander à l'utilisateur de se connecter, puis renvoyer les modifications une fois que l'utilisateur a été autorisé. Cependant, ce qui est réellement renvoyé par l'application MVC est un état "302 trouvé" et une URL de redirection vers ma page de formulaire de connexion. La page de formulaire de connexion renvoie un code d'état "200 OK" et l'objet jquery ajax appelle l'événement de réussite qui indique à l'utilisateur que tout a réussi, car c'est ce que dit l'application MVC.Vérification de l'autorisation http dans mvc avant le poste de formulaire ajax

Existe-t-il un moyen pour que l'application MVC fonctionne comme je le pense ou dois-je modifier mes événements jquery ajax pour détecter la page de connexion?

Mise à jour:

J'ai réflecteur utilisé pour un coup d'oeil dans le code MVC et l'attribut AUTORISER renvoyer un NotAuthorizedResult le code qui est en dessous (0x191 = 401)

public override void ExecuteResult(ControllerContext context) 
{ 
    if (context == null) 
    { 
     throw new ArgumentNullException("context"); 
    } 
    context.HttpContext.Response.StatusCode = 0x191; 
} 

Je pense que peut-être l'autorisation de formulaires HttpModule voit le 401 et forçant la redirection.

Répondre

6

vous pouvez essayer quelque chose comme ceci:

void context_EndRequest(object sender, EventArgs e) 
    { 
     var app = sender as HttpApplication; 
     var response = app.Response; 
     var request = app.Request; 

     if ((response.StatusCode == 302) && IsAjaxRequest(request)) 
      response.StatusCode = 401; 
    } 

dans un HttpModule, ce sera après le module FormsAuth en séquence afin corrigera le code d'état. Pas joli mais efficace.

+0

Dans .Net 4.0 (peut-être d'autres versions aussi, je ne sais pas), FormsAuthentication effectue la redirection dans le gestionnaire EndRequest.J'ai trouvé que FormsAuth n'avait pas traité la réponse si j'ai utilisé EndRequest, mais en utilisant l'événement PreSendRequestHeaders a fonctionné beaucoup mieux (vient après EndRequest). Merci pour ce super article. – womp

5

J'aime vraiment cette solution. En changeant la réponse 302 sur les requêtes ajax en 401, il vous permet de configurer votre ajax côté client pour surveiller toute requête ajax à la recherche d'un 401 et s'il en trouve un à rediriger vers la page de connexion. Très simple et efficace.

Global.asax:

protected void Application_EndRequest() 
{ 
    if (Context.Response.StatusCode == 302 && 
     Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest") 
    { 
     Context.Response.Clear(); 
     Context.Response.StatusCode = 401; 
    } 
} 

client Code Side:

$(function() { 
     $.ajaxSetup({ 
     statusCode: { 
      401: function() { 
      location.href = '/Logon.aspx?ReturnUrl=' + location.pathname; 
      } 
     } 
     }); 
    }); 
1

J'ai trouvé qu'une approche plus légère est tout simplement d'ajouter un en-tête HTTP personnalisé à la page de connexion, puis vérifiez pour la présence de cela dans le rappel de succès AJAX.

Ie. dans le LoginController (ce qui est un projet MVC, mais le même principe devrait appliquer pour d'autres solutions ASP.NET):

public ActionResult Login(string returnUrl = "") 
{ 
    Response.AddHeader("X-Unauthorized", "true"); 
    ... 

Et puis dans le gestionnaire AJAX côté client:

success: function(data, textStatus, jqXhr) 
{ 
    if (jqXhr.getResponseHeader("X-Unauthorized")) 
    { 
     ... 

Cela fonctionne pour moi au moins.

Questions connexes