2013-11-21 21 views
33

Sto lavorando all'applicazione 'ASP.NET MVC 4'. Sto usando/apprendo SimpleMembershipProvider e cerco di attenermi alla logica predefinita creata da VS2012 con lo Internet template (se non sbaglio, quello con "SimpleMembershipProvider" appena estratto dalla confezione).Come dovrei usare ReturnUrl = ViewBag.ReturnUrl in MVC 4

Sono bloccato al AccountController in cui non riesco proprio a capire come esattamente mettere posso usare questo metodo:

private ActionResult RedirectToLocal(string returnUrl) 
     { 
      if (Url.IsLocalUrl(returnUrl)) 
      { 
       return Redirect(returnUrl); 
      } 
      else 
      { 
       return RedirectToAction("Index", "Home"); 
      } 
     } 

Da quello che ho capito l'idea è quella di ottenere reindirizzato alla posizione da cui hai deciso di accedere (esattamente quello che voglio realizzare). Ho preso uno sguardo a come viene utilizzato nella vista:

@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) 

cercare un posto in cui in realtà ViewBag.ReturnUrl è impostato con un certo valore e ho solo ottenuto questo metodo qui:

[AllowAnonymous] 
public ActionResult Login(string returnUrl) 
{ 
    ViewBag.ReturnUrl = returnUrl; 
    return View(); 
} 

e sono diventando piuttosto confuso su come esattamente dovrei ottenere la posizione/url. Ho impostato alcuni punti di interruzione e non ho mai visto returnUrl essere qualcosa di diverso da null che in questo scenario mi sembra abbastanza logico dal momento che non ottiene alcun valore da nessuna parte (a meno che mi manchi qualcosa ovviamente).

Quindi non riesco davvero a capire come funziona. Pubblico quanto sopra solo per dimostrare che ho provato a fare i compiti, ho indagato il più possibile ma non ho trovato una risposta, quindi chiedo qui. Potresti fornire spiegazioni/esempi su come funziona?

risposta

50

Quando si utilizza l'autenticazione di moduli e l'utente non è autenticato o autorizzato l'ASP.La pipeline di sicurezza NET reindirizzerà alla pagina di accesso e passerà come parametro nella stringa di query returnUrl uguale alla pagina reindirizzata alla pagina di accesso. L'azione di login acquisisce il valore di questo parametro e lo inserisce nel ViewBag in modo che possa essere passato alla vista.

[AllowAnonymous] 
    public ActionResult Login(string returnUrl) 
    { 
     ViewBag.ReturnUrl = returnUrl; 
     return View(); 
    } 

La vista quindi memorizza questo valore nel modulo come mostrato da questa riga di codice nella vista.

@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) 

Il motivo per cui viene memorizzato nella vista è così che quando l'utente fa un Invia dopo aver inserito il nome utente e la password, l'azione di controllo che gestisce la parte posteriore postale avranno accesso a questo valore.

[HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public ActionResult Login(LoginModel model, string returnUrl) 
    { 
     if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe)) 
     { 
      return RedirectToLocal(returnUrl); 
     } 

     // If we got this far, something failed, redisplay form 
     ModelState.AddModelError("", "The user name or password provided is incorrect."); 
     return View(model); 
    } 

Se lo stato modello è valido e sono autenticato chiamando il metodo WebSecurity.Login allora chiama il metodo RedirectToLocal con il valore di ReturnURL che è venuto dalla vista, che è venuto in origine forma l'azione di accesso che ha creato la vista.

Il valore returnUrl sarà null se l'utente non viene reindirizzato alla pagina di accesso come avviene quando fa clic sul collegamento di accesso nella parte superiore della pagina nel layout predefinito. In questo caso l'utente verrà reindirizzato alla pagina iniziale dopo il login riuscito. L'intero scopo di returnUrl è di inviare automaticamente l'utente alla pagina a cui stavano tentando di accedere prima che venissero autenticati/autorizzati.

+0

Bene, ho questa domanda - 'returnUrl' è abbastanza affidabile da basare il controllo condizionale su di esso. Quello che voglio è implementare una logica specifica se il reindirizzamento è da 'AdminController' che in questo caso è 'returnUrl =/admin' stringa. Anche se penso di iniziare a capire come funzionano le cose sono ancora in dubbio se questa variabile è abbastanza sicura o può essere facilmente modificata? – Leron

+0

Non è sicuro e può essere facilmente modificato poiché si trova nella stringa di query. Chiunque può modificare questo valore nel proprio browser web. –

+0

questo non ha funzionato per me. Tuttavia puoi sempre fare: HttpContext.Request.Params ["ReturnUrl"]; – Tomer

3

Quando un utente non autenticato tenta di entrare in una sezione dell'applicazione che richiede l'autenticazione, quindi returnUrl entra nell'immagine. L'URL richiesto dall'utente non autenticato viene sostanzialmente memorizzato in returnUrl.

Si può passare attraverso la PluralSight tutorial: Building Applications with ASP.NET MVC 4

+1

Grazie per aver condiviso un video. Per ora ho bisogno di una soluzione rapida, prima pensavo che il template generasse solo uno scaffold e dovevo cambiarlo con qualcosa del genere - 'new {ReturnUrl = ViewContext.HttpContext.Request.UrlReferrer.PathAndQuery})' ma dopo il tuo post Ho fatto qualche altro test e sembra che tutto sia effettivamente integrato. Penso che la risposta sia nell'attributo [Authorize] e nella sua implementazione, ma sarebbe bello ottenere una spiegazione da qualcuno che abbia una buona comprensione. – Leron

10

Questo perché il modello di ASP.NET MVC predefinita utilizza Forms authentication e controllori sono decorate con [Authorize] attributo:

<authentication mode="Forms"> 
    <forms loginUrl="~/Account/Login" timeout="2880" /> 
</authentication> 

[Authorize] 
public class AccountController : Controller 
{ 
    //... 
} 

Ciò significa che se l'utente non è autenticato verrà reindirizzato alla pagina di accesso definita nell'attributo LoginUrl dell'elemento forms.

Durante il reindirizzamento, FormsAuthentication che è un HttpModule aggiungerà automaticamente l'URL che è stato richiesto nella stringa di query.

Quindi, se si passa a /Account/Login, non si ottiene nulla nella stringa di query poiché è decorato con l'attributo [AllowAnonymous]. Ma se si passa a /Account/Manage si noterà che il ReturnURL nella stringa di query diventa /Account/Manage(/Account/Login?ReturnUrl=%2fAccount%2fManage)

Quindi non sta impostando l'ReturnURL, il quadro che fa per voi, è sufficiente utilizzare nella AccountController di sapere dove per reindirizzare l'utente dopo che è stato autenticato.