Перенаправление из атрибута фильтра действий - PullRequest
122 голосов
/ 28 марта 2011

Каков наилучший способ сделать перенаправление в ActionFilterAttribute. У меня есть ActionFilterAttribute с именем IsAuthenticatedAttributeFilter, и он проверил значение переменной сеанса. Если переменная имеет значение false, я хочу, чтобы приложение перенаправляло на страницу входа. Я бы предпочел перенаправить, используя имя маршрута SystemLogin, однако любой метод перенаправления на этом этапе будет в порядке.

Ответы [ 8 ]

166 голосов
/ 28 марта 2011

Установить filterContext.Result

С именем маршрута:

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

Вы также можете сделать что-то вроде:

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

Если вы хотите использовать RedirectToAction:

Вы можете сделать публичный RedirectToAction метод на вашем контроллере ( предпочтительно на его базовом контроллере ), который просто вызывает защищенный RedirectToActionот 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");
}
70 голосов
/ 20 июля 2013

В качестве альтернативы перенаправлению, если он вызывает ваш собственный код, вы можете использовать это:

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

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

Это не просто перенаправление, но дает аналогичный результат без ненужных накладных расходов.

12 голосов
/ 01 октября 2013

Я использую MVC4, я использовал следующий подход, чтобы перенаправить пользовательский HTML-экран при нарушении авторизации.

Расширить AuthorizeAttribute скажем CutomAuthorizer переопределить OnAuthorization и HandleUnauthorizedRequest

Зарегистрируйте 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 голосов
/ 28 марта 2011

Звучит так, как будто вы хотите повторно внедрить или, возможно, расширить 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 голосов
/ 07 мая 2013

Попробуйте следующий фрагмент, он должен быть довольно ясным:

1 голос
/ 13 марта 2018

Вот решение, которое также учитывает, если вы используете запросы 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);
        }
    }
}
0 голосов
/ 12 ноября 2018

Это работает для меня (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 голосов
/ 07 мая 2013

вы можете унаследовать свой контроллер, а затем использовать его внутри фильтра действий

внутри вашего класса 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); 
    }
}

Cons. это изменить все контроллеры для наследования от класса "MyController"

...