2009-06-03 92 views
5

J'ai quelques méthodes d'action derrière un Autorisez comme:Plus de contrôle sur l'autorisation d'ASP.Net MVC; de garder les requêtes AJAX AJAXy

[AcceptVerbs(HttpVerbs.Post), Authorize] 
public ActionResult Create(int siteId, Comment comment) { 

Le problème était que j'envoie une demande par AJAX à commenter/Créer avec

X-Requested-With=XMLHttpRequest 

ce qui aide à identifier la requête en AJAX. Lorsque l'utilisateur n'est pas connecté et atteint le mur Authorize, il est redirigé vers

/Account/LogOn?ReturnUrl=Comment%2fCreate 

qui interrompt le flux de travail AJAX. Je dois être redirigé vers

/Account/LogOn?X-Requested-With=XMLHttpRequest 

Des idées comment cela peut-il être réalisé? Des moyens d'obtenir plus de contrôle sur ce qui se passe lorsque l'autorisation est demandée? Au lieu d'utiliser l'attribut authorize, j'ai fait quelque chose comme le suivant:

Répondre

5

Merci aux commentaires de Lewis j'ai pu arriver à cette solution (qui est loin d'être parfait, affiché avec mes propres commentaires, si vous avez les corrections ne hésitez pas à modifier et de supprimer cette phrase), mais il fonctionne:

public class AjaxAuthorizeAttribute : AuthorizeAttribute { 
    override public void OnAuthorization(AuthorizationContext filterContext) { 
     base.OnAuthorization(filterContext); 
     // Only do something if we are about to give a HttpUnauthorizedResult and we are in AJAX mode. 
     if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest()) { 
      // TODO: fix the URL building: 
      // 1- Use some class to build URLs just in case LoginUrl actually has some query already. 
      // 2- When leaving Result as a HttpUnauthorizedResult, ASP.Net actually does some nice automatic stuff, like adding a ReturnURL, when hardcodding the URL here, that is lost. 
      String url = System.Web.Security.FormsAuthentication.LoginUrl + "?X-Requested-With=XMLHttpRequest"; 
      filterContext.Result = new RedirectResult(url); 
     } 
    } 
} 
+0

Bon exemple. Mais comment tester base.OnAuthorization (filterContext); invocation? – Ofigenn

+0

une autre approche pour ce problème est décrite par [Kevin Craft] (http://craftycodeblog.com/2010/05/15/asp-net-mvc-ajax-redirect/) – Towa

1

public ActionResult SomeCall(string someData) 
{ 
    if (Request.IsAjaxRequest() == false) 
    { 
     // TODO: do the intended thing. 
    } 
    else 
    { 
     // This should only work with AJAX requests, so redirect 
     // the user to an appropriate location. 
     return RedirectToAction("Action", "Controller", new { id = ?? }); 
    } 
} 
+0

J'ai déjà compris cette partie. Mon problème est que cette méthode a un Authorize en face de lui et la redirection de l'Authorize perd la capacité d'être vérifiée pour AJAX comme vous l'avez fait. – Pablo

0

Je pense que la bonne façon de gérer cela serait dans votre Javascript faisant l'appel AJAX.

Si l'utilisateur a besoin d'être autorisé (ou authentifié comme votre code l'indique) et qu'il ne l'est pas, vous devez l'informer et peut-être ne pas lui permettre d'essayer et de commenter en premier lieu.

Cependant, si cela ne vous convient pas. Vous pouvez essayer d'écrire votre propre filtre d'action, en héritant peut-être de celui fourni avec le framework MVC, mais en redirigeant comme vous le souhaitez. C'est assez simple.

+0

Je veux qu'ils essaient de commenter et de participer au site et vous invitent seulement à vous connecter si nécessaire. Il n'y a aucun moyen dans le code JavaScript que je puisse savoir si l'utilisateur est connecté sans faire un appel AJAX pour vérifier cela en premier et ensuite essayer d'exécuter cette fonction. J'ai aimé votre idée de faire un autre filtre d'action, mais après avoir joué avec cela un peu il ne semble pas contrôler où l'utilisateur est redirigé. Savez-vous à coup sûr que c'est le cas? D'autres indices? – Pablo

+0

Mon mauvais, maintenant je l'ai trouvé. Merci pour le pointeur dans la bonne direction Lewis. – Pablo

3

Récemment, j'ai rencontré exactement le même problème et utilisé le code publié par J. Pablo Fernández avec une modification pour tenir compte des URL de retour. Le voici:

public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute 
{ 
    override public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     base.OnAuthorization(filterContext); 
     // Only do something if we are about to give a HttpUnauthorizedResult and we are in AJAX mode. 
     if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest()) 
     { 
      // TODO: fix the URL building: 
      // 1- Use some class to build URLs just in case LoginUrl actually has some query already. 
      HttpRequestBase request = filterContext.HttpContext.Request; 
      string returnUrl = request.Path; 
      bool queryStringPresent = request.QueryString.Count > 0; 
      if (queryStringPresent || request.Form.Count > 0) 
       returnUrl += '?' + request.QueryString.ToString(); 
      if (queryStringPresent) 
       returnUrl += '&'; 
      returnUrl += request.Form; 
      String url = System.Web.Security.FormsAuthentication.LoginUrl + 
         "?X-Requested-With=XMLHttpRequest&ReturnUrl=" + 
         HttpUtility.UrlEncode(returnUrl); 
      filterContext.Result = new RedirectResult(url); 
     } 
    } 
}