[Authorize]
l'attribut est une invention MS agréable et pratique, et j'espère qu'il pourra résoudre les problèmes que j'ai maintenant
Pour être plus précis:
Lorsque le client actuel n'est pas authentifié - [Authorize]
redirige l'action sécurisée vers la page de connexion et une fois la connexion réussie - ramène l'utilisateur, c'est bien.
Mais lorsque le client actuel est déjà authentifié mais n'est pas autorisé à exécuter une action spécifique - tout ce dont j'ai besoin est simplement d'afficher ma page 403 générale.
Est-ce possible sans déplacer la logique d'autorisation dans le corps du contrôleur?
pdate: Le comportement dont j'ai besoin devrait être sémantiquement égal à ce croquis:
public ActionResult DoWork()
{
if (!NotAuthorized())
{
// this should be not redirect, but forwarding
return RedirectToAction("403");
}
return View();
}
donc - il ne doit pas y avoir de redirection et l'url doit rester la même, mais le contenu de la page doit être remplacé par 403 pages
pdate 2: J'ai implémenté le sketch de cette façon:
[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" };
}
}
Et ne peut pas savoir comment transmettre correctement l'exécution à HomeController.Action_403 () pour qu'il affiche 403.
mise à jour:
filterContext.Result = new ViewResult() { ViewName = "Error_403" };
c'est donc une réponse sur la façon de rendre un modèle de vue spécifique ... mais je n'ai toujours aucune idée de comment exécuter un autre contrôleur - de toute façon, c'est une assez bonne solution.
Vous devriez pouvoir créer votre propre classe qui dérive de AuthorizeAttribute
et remplacer la méthode AuthorizeCore
pour fournir le mécanisme d'autorisation que vous souhaitez , afin que vous puissiez appliquer votre code d'autorisation personnalisé en utilisant un attribut au lieu de le déplacer dans le contrôleur.
Si vous avez besoin d'un contrôle plus fin sur l'autorisation, je vous recommande de créer une implémentation de l'interface IActionFilter
(sur un attribut, puis appliquez l'attribut à vos méthodes). Cela vous permettra d'intercepter les appels avant qu'ils ne parviennent au contrôleur et de fournir des actions alternatives avant d'appeler votre méthode de contrôleur.
Ceci est réalisé en implémentant la méthode OnActionExecuting
sur l'interface IActionFilter
. Si votre logique détermine que vous ne devez pas du tout appeler le contrôleur et que vous souhaitez fournir un ActionResult
à traiter à la place, vous devez définir le Result
property sur l'instance ActionExecutingContext
passée dans la méthode. Ce faisant, ce ActionResult
est traité au lieu d'aller à la méthode du contrôleur pour obtenir un ActionResult
.
Si vous souhaitez renvoyer un code d'erreur 403, vous ne pouvez pas utiliser la classe ContentResult
. Vous devrez créer votre propre classe qui dérive de ActionResult
et remplacer la méthode ExecuteResult
pour définir la propriété StatusCode
= sur le HttpResponseBase
à 403, comme ceci:
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();
}
}
Bien sûr, vous pouvez généraliser le Http403Result
classe pour prendre un constructeur qui acceptera le code d'état que vous souhaitez renvoyer, mais le concept reste le même.
Ce que je ferais, c'est sous-classe AuthorizeAttribute et remplacer son HandleUnauthorizedRequest pour retourner le code d'état HTTP 403 si l'utilisateur est authentifié. J'ajouterais alors une section system.webServer\httpErrors à mon Web.Config pour remplacer le 403 par défaut avec ma page personnalisée (cette dernière partie nécessite IIS 7+). Voici comment:
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>