从动作过滤器属性重定向


139

在中进行重定向的最佳方法是什么ActionFilterAttribute?我有一个ActionFilterAttribute电话,IsAuthenticatedAttributeFilter并检查了会话变量的值。如果变量为false,则我希望应用程序重定向到登录页面。我更愿意使用路由名称进行重定向,SystemLogin但是此时任何重定向方法都可以。


Answers:


186

设置filterContext.Result

带有路线名称:

filterContext.Result = new RedirectToRouteResult("SystemLogin", routeValues);

您还可以执行以下操作:

filterContext.Result = new ViewResult
{
    ViewName = SharedViews.SessionLost,
    ViewData = filterContext.Controller.ViewData
};

如果要使用RedirectToAction

您可以RedirectToAction在控制器(最好在其基本控制器)上创建一个公共方法,该方法只需调用protected RedirectToActionfrom System.Web.Mvc.Controller。添加此方法可允许 RedirectToAction从过滤器中公开呼叫

public new RedirectToRouteResult RedirectToAction(string action, string controller)
{
    return base.RedirectToAction(action, controller);
}

然后,您的过滤器将类似于:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var controller = (SomeControllerBase) filterContext.Controller;
    filterContext.Result = controller.RedirectToAction("index", "home");
}

8
这可行,但是不应该有RedirectToAction方法吗?
本·米尔斯

@BenMills有,但是,protected这样您就无法从过滤器访问它。
詹姆斯

10
现在我的问题是,Microsoft为什么决定使此筛选器protected必须有一些合理的解释?重新定义这种可访问性的过程让我感到非常肮脏,RedirectToAction但却没有理解为什么首先将其封装。
马修·马林2015年

2
@MatthewMarlin-有关重定向到操作的正确答案,请参见Syakur的答案。正确的是,您不应该直接从动作过滤器中调用控制器-这是紧密耦合的定义。
NightOwl888 '16

1
@Akbari您是否尝试设置属性的Order属性?FilterScope也会影响执行顺序。
CRice

79

作为重定向的替代方法,如果它正在调用您自己的代码,则可以使用以下命令:

actionContext.Result = new RedirectToRouteResult(
    new RouteValueDictionary(new { controller = "Home", action = "Error" })
);

actionContext.Result.ExecuteResult(actionContext.Controller.ControllerContext);

它不是纯粹的重定向,但会产生类似的结果而没有不必要的开销。


您可以帮我。谢谢!
Edgar Salazar 2015年

25
请注意,您不应actionContext.Result.ExecuteResult从操作过滤器中进行调用-MVC将在操作过滤器运行后自动执行此操作(提供的actionContext.Result值不为null)。
NightOwl888 '16

12

我正在使用MVC4,我使用以下方法在违反授权时重定向自定义html屏幕。

扩展AuthorizeAttributeCutomAuthorizer 覆盖OnAuthorizationHandleUnauthorizedRequest

CustomAuthorizer中注册RegisterGlobalFilters

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{

    filters.Add(new CustomAuthorizer());
}

在确定 unAuthorized访问呼叫HandleUnauthorizedRequest并重定向到相关的控制器操作,如下所示。


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" }

                                         });

    }
}

9

听起来您想重新实现或可能扩展AuthorizeAttribute。如果是这样,则应确保您继承了它,而不是ActionFilterAttribute以便让ASP.NET MVC为您完成更多工作。

另外,您还想确保在执行操作方法中的任何实际工作之前已获得授权-否则,已登录和未登录之间的唯一区别是完成工作后所看到的页面。

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);
    }
}

这里有一个很好的问题答案有更多关于SO的细节。


5

尝试以下代码片段,应该很清楚:

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);
  }
}

这对我有用,如果有任何用户尝试更改查询字符串值并尝试访问未经他/她授权的数据,则我必须检查查询字符串值,而不是使用ActionFilterAttribute将其重定向到未经授权的消息页面。
Sameer

3

如果您使用的是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);
        }
    }
}

1

这对我有用(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();
}

0

您可以继承控制器,然后在动作过滤器中使用它

在ActionFilterAttribute类中:

   if( filterContext.Controller is MyController )
      if(filterContext.HttpContext.Session["login"] == null)
           (filterContext.Controller as MyController).RedirectToAction("Login");

在您的基本控制器中:

public class MyController : Controller 
{
    public void  RedirectToAction(string actionName) { 
        base.RedirectToAction(actionName); 
    }
}

缺点 这是将所有控制器更改为继承自“ MyController”类

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.