2013-04-30 11 views
12

In un progetto ASP.NET MVC, quando si decora una classe o un metodo con [Autorizza] e l'autorizzazione non riesce, il sito reindirizza automaticamente alla pagina di accesso (utilizzando l'account loginUrl specificato nel Web config). Inoltre, qualcosa nel framework ASP.NET MVC passa lungo l'URL della richiesta originale come parametro ReturnUrl.Cosa imposta inizialmente il parametro ReturnUrl quando si utilizza AuthorizeAttribute

Qual è la responsabilità di aggiungere questo ReturnUrl? Non sono riuscito a trovare alcun codice per questo nel modello di progetto. Ho anche dato un'occhiata al codice per AuthorizeAttribute nello stack ASP.NET source code ma non ho trovato nulla lì. Ho anche provato a cercare l'intero codice sorgente dello stack ASP.NET per "returnurl" ma non sono riuscito a trovare nulla.

La ragione per cui chiedo è che ho scoperto un bug in questo processo. Puoi vederlo con un nuovissimo progetto Internet ASP.NET MVC. Impostare il timeout FormsAuth su 1 minuto in web.config e quindi accedere. Attendere oltre un minuto e provare ad uscire. Ciò reindirizzerà alla pagina di login con un ReturnUrl di/account/disconnessione, che porta ad una 404 dopo l'accesso ho lavorato intorno a questo, per ora con la mia AuthorizeAttribute:.

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     base.OnAuthorization(filterContext); 

     if (filterContext.Result is HttpUnauthorizedResult) 
     { 
      string returnUrl = null; 
      if (filterContext.HttpContext.Request.HttpMethod.Equals("GET", System.StringComparison.CurrentCultureIgnoreCase)) 
       returnUrl = filterContext.HttpContext.Request.RawUrl; 

      filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary() 
      { 
       { "client", filterContext.RouteData.Values[ "client" ] }, 
       { "controller", "Account" }, 
       { "action", "Login" }, 
       { "ReturnUrl", returnUrl } 
      }); 
     } 
    } 
} 

Tuttavia, vorrei dare un'occhiata alla fonte e vedere se riesco a capire perché questo bug esiste, se è davvero un bug.

+0

Penso che faccia parte dell'autenticazione di moduli non solo specifica per MVC. L'URL di ritorno esiste anche in WebForm – Devesh

+0

Potrebbe essere - Presumo che fosse qualcosa correlato a MVC poiché AuthorizationAttribute si trova nello spazio dei nomi MVC e l'override di OnAuthorization (come mostrato sopra) sembra aggirare il problema. –

+0

http://msdn.microsoft.com/en-us/library/ff647070.aspx, può essere d'aiuto – Devesh

risposta

10

Il parametro querystring returnUrl viene aggiunto al reindirizzamento alla pagina di accesso all'interno della classe FormsAuthentication nell'assembly System.Web.dll. Gli overload dei metodi FormsAuthenticion.RedirectToLoginPage terminano chiamando il metodo interno, GetLoginPage. Sia il nome della variabile "ReturnUrl" che LoginUrl possono essere sovrascritti tramite le impostazioni web.config.

Quando il default AuthorizeAttribute incontra una richiesta non autorizzata, semplicemente restituisce un HttpUnauthorizedResult, che è solo un involucro intorno al HttpStatusCodeResult con un codice di stato di 401. Il FormsAuthenticationModule calci nel dietro le quinte e fa il resto del lavoro. Non esiste un'interazione diretta tra MVC e queste classi di base, a meno che, naturalmente, non si stia chiamando direttamente i metodi statici della classe FormsAuthentication.

La soluzione è di tipo standard quando si desidera eseguire l'override di questo comportamento.

Il metodo getLoginPage che fa il lavoro è la seguente:

internal static string GetLoginPage(string extraQueryString, bool reuseReturnUrl) 
{ 
    HttpContext current = HttpContext.Current; 
    string loginUrl = FormsAuthentication.LoginUrl; 
    if (loginUrl.IndexOf('?') >= 0) 
    { 
     loginUrl = FormsAuthentication.RemoveQueryStringVariableFromUrl(loginUrl, FormsAuthentication.ReturnUrlVar); 
    } 
    int num = loginUrl.IndexOf('?'); 
    if (num >= 0) 
    { 
     if (num < loginUrl.Length - 1) 
     { 
      loginUrl = string.Concat(loginUrl, "&"); 
     } 
    } 
    else 
    { 
     loginUrl = string.Concat(loginUrl, "?"); 
    } 
    string str = null; 
    if (reuseReturnUrl) 
    { 
     str = HttpUtility.UrlEncode(FormsAuthentication.GetReturnUrl(false), current.Request.QueryStringEncoding); 
    } 
    if (str == null) 
    { 
     str = HttpUtility.UrlEncode(current.Request.RawUrl, current.Request.ContentEncoding); 
    } 
    loginUrl = string.Concat(loginUrl, FormsAuthentication.ReturnUrlVar, "=", str); 
    if (!string.IsNullOrEmpty(extraQueryString)) 
    { 
     loginUrl = string.Concat(loginUrl, "&", extraQueryString); 
    } 
    return loginUrl; 
} 
Problemi correlati