Quelle est la meilleure façon de faire une redirection dans une ActionFilterAttribute
. J'ai une ActionFilterAttribute
appelée IsAuthenticatedAttributeFilter
et qui vérifie la valeur d'une variable de session. Si la variable est false, je souhaite que l'application soit redirigée vers la page de connexion. Je préférerais rediriger en utilisant le nom de la route SystemLogin
mais toute méthode de redirection à ce stade serait satisfaisante.
Définir filterContext.Result
Avec le nom de la route:
filterContext.Result = new RedirectToRouteResult("SystemLogin", routeValues);
Vous pouvez aussi faire quelque chose comme:
filterContext.Result = new ViewResult
{
ViewName = SharedViews.SessionLost,
ViewData = filterContext.Controller.ViewData
};
Si vous voulez utiliser RedirectToAction
:
Vous pouvez créer une méthode publique RedirectToAction
sur votre contrôleur (de préférence sur son contrôleur de base) qui appelle simplement la valeur protégée RedirectToAction
à partir de System.Web.Mvc.Controller
. L'ajout de cette méthode permet un appel public à votreRedirectToAction
à partir du filtre.
public new RedirectToRouteResult RedirectToAction(string action, string controller)
{
return base.RedirectToAction(action, controller);
}
Ensuite, votre filtre ressemblerait à quelque chose comme:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var controller = (SomeControllerBase) filterContext.Controller;
filterContext.Result = controller.RedirectToAction("index", "home");
}
Alternativement à une redirection, si elle appelle votre propre code, vous pouvez utiliser ceci:
actionContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new { controller = "Home", action = "Error" })
);
actionContext.Result.ExecuteResult(actionContext.Controller.ControllerContext);
Ce n'est pas une redirection pure mais donne un résultat similaire sans surcharge inutile.
J'utilise MVC4, j'ai utilisé l'approche suivante pour rediriger un écran HTML personnalisé en cas de violation de l'autorisation.
Étendre AuthorizeAttribute
dire CutomAuthorizer
Remplacer les OnAuthorization
et HandleUnauthorizedRequest
Enregistrez la CustomAuthorizer
dans la RegisterGlobalFilters
.
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomAuthorizer());
}
lors de l'identification de unAuthorized
accès, appelez HandleUnauthorizedRequest
et redirigez vers l'action du contrôleur concerné, comme indiqué ci-dessous.
public class CustomAuthorizer : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
bool isAuthorized = IsAuthorized(filterContext); // check authorization
base.OnAuthorization(filterContext);
if (!isAuthorized && !filterContext.ActionDescriptor.ActionName.Equals("Unauthorized", StringComparison.InvariantCultureIgnoreCase)
&& !filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.Equals("LogOn", StringComparison.InvariantCultureIgnoreCase))
{
HandleUnauthorizedRequest(filterContext);
}
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result =
new RedirectToRouteResult(
new RouteValueDictionary{{ "controller", "LogOn" },
{ "action", "Unauthorized" }
});
}
}
Il semble que vous souhaitiez ré-implémenter, ou éventuellement étendre, AuthorizeAttribute
. Si tel est le cas, vous devez vous assurer que vous héritez de cela, et non de ActionFilterAttribute
, afin de permettre à ASP.NET MVC de se charger davantage du travail à votre place.
En outre, vous voulez vous assurer que vous autorisez avant que ne réalisiez aucun travail réel dans la méthode d'action - sinon, la seule différence entre connecté et non connecté sera la page que vous voyez lorsque le travail est terminé.
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
// Do whatever checking you need here
// If you want the base check as well (against users/roles) call
base.OnAuthorization(filterContext);
}
}
Il y a une bonne question avec une réponse avec plus de détails ici sur SO.
Essayez l'extrait suivant, cela devrait être assez clair:
public class AuthorizeActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(FilterExecutingContext filterContext)
{
HttpSessionStateBase session = filterContext.HttpContext.Session;
Controller controller = filterContext.Controller as Controller;
if (controller != null)
{
if (session["Login"] == null)
{
filterContext.Cancel = true;
controller.HttpContext.Response.Redirect("./Login");
}
}
base.OnActionExecuting(filterContext);
}
}
Voici une solution qui prend également en compte si vous utilisez des requêtes Ajax.
using System;
using System.Web.Mvc;
using System.Web.Routing;
namespace YourNamespace{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeCustom : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext context) {
if (YourAuthorizationCheckGoesHere) {
string area = "";// leave empty if not using area's
string controller = "ControllerName";
string action = "ActionName";
var urlHelper = new UrlHelper(context.RequestContext);
if (context.HttpContext.Request.IsAjaxRequest()){ // Check if Ajax
if(area == string.Empty)
context.HttpContext.Response.Write($"<script>window.location.reload('{urlHelper.Content(System.IO.Path.Combine(controller, action))}');</script>");
else
context.HttpContext.Response.Write($"<script>window.location.reload('{urlHelper.Content(System.IO.Path.Combine(area, controller, action))}');</script>");
} else // Non Ajax Request
context.Result = new RedirectToRouteResult(new RouteValueDictionary( new{ area, controller, action }));
}
base.OnActionExecuting(context);
}
}
}
Cela fonctionne pour moi (asp.net core 2.1)
using JustRide.Web.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace MyProject.Web.Filters
{
public class IsAuthenticatedAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.HttpContext.User.Identity.IsAuthenticated)
context.Result = new RedirectToActionResult(nameof(AccountController.Index), "Account", null);
}
}
}
[AllowAnonymous, IsAuthenticated]
public IActionResult Index()
{
return View();
}
vous pouvez hériter de votre contrôleur puis l'utiliser à l'intérieur de votre filtre d'action
dans votre classe ActionFilterAttribute:
if( filterContext.Controller is MyController )
if(filterContext.HttpContext.Session["login"] == null)
(filterContext.Controller as MyController).RedirectToAction("Login");
dans votre contrôleur de base:
public class MyController : Controller
{
public void RedirectToAction(string actionName) {
base.RedirectToAction(actionName);
}
}
Les inconvénients. cela consiste à changer tous les contrôleurs pour hériter de la classe "MyController"