2010-04-05 10 views
44

[Authorize] attributo è bello e utile invenzione MS, e spero che possa risolvere i problemi che ho adessoCome fare Autorizza attribuire tornare personalizzato 403 pagina di errore invece di reindirizzamento alla pagina di accesso

Per essere più precisi:

Quando client corrente non viene autenticato - [Authorize] reindirizza da azione messa in sicurezza alla pagina di accesso e dopo l'accesso ha avuto successo - riporta utente indietro, questo è buono.

Ma quando client corrente già autenticato ma non autorizzato a eseguire un'azione specifica - tutto quello che serve è di visualizzare solo il mio generale 403 pagina.

E 'possibile senza spostare la logica di autorizzazione all'interno del corpo del controllore?

Aggiornamento: Il comportamento ho bisogno dovrebbe essere semanticamente uguale a questo schizzo:

public ActionResult DoWork() 
{ 
    if (!NotAuthorized()) 
    { 
     // this should be not redirect, but forwarding 
     return RedirectToAction("403");   
    } 

    return View(); 
} 

così - ci dovrebbe senza alcun redirect e URL deve essere rimanere lo stesso, ma il contenuto della pagina dovrebbe essere sostituito con 403 pagine

Update 2: ho implementato schizzo in questo modo:

[HandleError] 
public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     ViewData["Message"] = "Welcome to ASP.NET MVC!"; 

     return View(); 
    } 

    [CustomActionFilter] 
    public ActionResult About() 
    { 
     return View(); 
    } 

    public ActionResult Error_403() 
    { 
     return Content("403"); 
    } 
} 

public class CustomActionFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     filterContext.Result = new ContentResult { Content = "403" }; 
    } 
} 

e non può ottenere come correttamente l'ora di esecuzione per HomeController.Action_403() in modo che visualizzi 403.

Update 3:

filterContext.Result = new ViewResult() { ViewName = "Error_403" }; 

quindi questa è una risposta su come rendere specifica guarda il modello ... ma non hai ancora idea di come eseguire un altro controller - comunque, è una buona soluzione.

+0

@casperOne: perché diavolo hai aggiunto il commento com'era dalla mia persona ??? – zerkms

+0

Il commento sul lato ostacola la leggibilità del codice. Posizionandolo sopra impedisce la visualizzazione delle barre di scorrimento ed è solo una parte del processo di pulizia. – casperOne

+0

@casperOne: sono un idiota e ho bisogno di occhiali, mi dispiace ;-( – zerkms

risposta

30

Si dovrebbe essere in grado di creare la propria classe che deriva da AuthorizeAttribute e l'override del metodo AuthorizeCore per fornire il meccanismo di autorizzazione che si desidera, in modo che è possibile applicare il codice di autorizzazione personalizzato utilizzando un attributo invece di spostarlo nella controller.

Se è necessario un controllo più dettagliato sull'autorizzazione, si consiglia di creare un'implementazione dell'interfaccia IActionFilter (su un attributo, quindi applicare l'attributo ai propri metodi). Ciò ti consentirà di intercettare le chiamate prima di andare al controller e di fornire azioni alternative prima del il metodo del controller viene chiamato.

Ciò si ottiene implementando OnActionExecuting method nell'interfaccia IActionFilter. Se la logica determina che non si deve effettuare la chiamata al controller a tutti, e si desidera fornire un ActionResult da lavorare, invece, allora si dovrebbe impostare la Result property sull'istanza ActionExecutingContext passato nel metodo. Effettuando ciò, quello ActionResult si elabora invece che passa al metodo di controller per ottenere uno ActionResult.

Se si desidera restituire un codice di errore di 403, quindi non è possibile utilizzare la classe ContentResult.Si dovrà creare una classe che deriva da ActionResult e l'override del metodo ExecuteResult per impostare il StatusCode property sul HttpResponseBase-403, in questo modo:

internal class Http403Result : ActionResult 
{ 
    public override void ExecuteResult(ControllerContext context) 
    { 
     // Set the response code to 403. 
     context.HttpContext.Response.StatusCode = 403; 
    } 
} 

public class CustomActionFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     filterContext.Result = new Http403Result(); 
    } 
} 

Naturalmente, si può generalizzare la classe Http403Result di prendere un costruttore che accetterà il codice di stato che si desidera restituire, ma il concetto rimane lo stesso.

+0

Quasi ciò di cui ho bisogno, ma AuthorizeCore restituisce booleano - il che significa che l'utente ha o meno accesso all'azione. L'implementazione predefinita contiene il reindirizzamento: è twivia, ma ho bisogno di sostituire l'output completo. – zerkms

+0

@zerkms: risposta aggiornata per fornire ulteriori informazioni su come sostituire l'output. – casperOne

+0

@casperOne: funziona correttamente con attivato in Web.config? Ho uno scenario leggermente diverso basato sulla tua soluzione (sto derivando da AuthorizeAttribute piuttosto che ActionFilterAttribute) e quando ritorna 403 non ottengo una pagina bella che è configurata nei miei in Web.config - invece ottengo un brutto schermo di IE. –

46

Quello che vorrei fare è sottoclasse AuthorizeAttribute e sovrascrivere HandleUnauthorizedRequest per restituire il codice di stato HTTP 403 se l'utente è autenticato. Vorrei quindi aggiungere una sezione system.webServer \ httpErrors al mio Web.Config per sostituire il 403 predefinito con la mia pagina personalizzata (quest'ultima parte richiede IIS 7+). Ecco come:

public class MyAuthorizeAttribute : AuthorizeAttribute { 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { 
     if (filterContext.HttpContext.User.Identity.IsAuthenticated) 
      filterContext.Result = new HttpStatusCodeResult(403); 
     else 
      filterContext.Result = new HttpUnauthorizedResult(); 
    } 
} 

<configuration> 
    <system.webServer> 
    <httpErrors errorMode="Custom" existingResponse="Replace"> 
     <remove statusCode="403" /> 
     <error statusCode="403" responseMode="ExecuteURL" path="/Error/MyCustom403page" /> 
    </httpErrors> 
    </system.webServer> 
</configuration> 
+0

Faresti meglio a fare una nuova domanda ;-) – zerkms

+0

Insieme al codice di stato, viene anche impostata la Descrizione dello stato. Come ottenere questa descrizione dello stato nella pagina/vista errore personalizzato 403? – Vishal

Problemi correlati