2009-06-03 9 views
5

Ho alcuni metodi d'azione dietro un Autorizza come:Più controllo su Autorizzazione di ASP.Net MVC; per mantenere AJAX richiede AJAXy

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

Il problema che ho è che sto inviando una richiesta attraverso AJAX per Commento/Crea con

X-Requested-With=XMLHttpRequest 

che aiuta a identificare la richiesta come AJAX. Quando l'utente non è connesso e colpisce il muro Autorizza si ottiene reindirizzato a

/Account/LogOn?ReturnUrl=Comment%2fCreate 

che rompe il flusso di lavoro AJAX. Devo essere reindirizzato a

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

Qualche idea su come sia possibile ottenerlo? Qualche modo per ottenere un maggiore controllo su ciò che accade quando viene richiesta l'autorizzazione?

risposta

5

grazie ai commenti di Lewis sono stato in grado di raggiungere questa soluzione (che è ben lungi dall'essere perfetto, inviato con i miei commenti, se avete le correzioni sentitevi liberi di modificare e rimuovere questa frase), ma funziona:

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

Ottimo esempio. Ma come testare base.OnAutorizzazione (filterContext); invocazione? – Ofigenn

+0

un altro aproach per questo problema è descritto da [Kevin Craft] (http://craftycodeblog.com/2010/05/15/asp-net-mvc-ajax-redirect/) – Towa

1

Invece di utilizzare l'attributo authorize, ho fatto qualcosa di simile al seguente.

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

Ho già capito quella parte. Il mio problema è che quel metodo ha un Autorizzato di fronte ad esso e il reindirizzamento dell'Autorizzazione perde la capacità di essere controllato per AJAX come hai fatto tu. – Pablo

0

Penso che il modo corretto per gestire questo sarebbe nel tuo Javascript effettuare la chiamata AJAX.

Se l'utente deve essere autorizzato (o autenticato come implica il codice) e non lo è, è necessario informarlo e forse non consentire loro di provare e commentare in primo luogo.

Tuttavia, se ciò non soddisfa le vostre esigenze. Si potrebbe provare a scrivere il proprio filtro di azione di autorizzazione, magari ereditando da quello fornito con il framework MVC, ma reindirizzando come si desidera. È abbastanza semplice.

+0

Voglio che provino a commentare e partecipare al sito e richiedono solo il log in quando necessario. Non c'è modo nel codice JavaScript che io possa sapere se l'utente è loggato senza effettuare una chiamata AJAX per controllarlo prima e poi provare a eseguire quella funzione. Mi è piaciuta l'idea di fare un altro filtro azione, ma dopo averlo giocato un po 'non sembra controllare dove viene reindirizzato l'utente. Sai per certo che lo fa? Qualche altro suggerimento? – Pablo

+0

Il mio male, ora l'ho trovato. Grazie per il puntatore nella giusta direzione Lewis. – Pablo

3

Recentemente mi sono imbattuto esattamente nello stesso problema e ho utilizzato il codice pubblicato da J. Pablo Fernández con una modifica per tenere conto degli URL di ritorno. Eccolo:

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); 
     } 
    } 
}