Лучший способ прервать/отменить действие и ответ от ActionFilter

Лучший способ прервать/отменить действие из ActionFilter

У меня есть этот ActionFilter, и он должен немедленно разорвать соединение и вернуть 401 Unauthroized:

public class SignInRequired : ActionFilterAttribute 
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // User is verified, continue executing action

        if (Acme.Web.CurrentUser != null)
        {
            return;
        }

        // End response with 401 Unauthorized

        var response = HttpContext.Current.Response;
        response.StatusCode = (int)HttpStatusCode.Unauthorized;
        response.End();

        // Prevent the action from actually being executed

        filterContext.Result = new EmptyResult();
    }
}

Я узнал, как отменить выполнение действия, установив 'context.Result = new EmptyResult()` здесь, но я не уверен, что это лучший способ сбросить ответ и закрыть соединение.


person AgileMeansDoAsLittleAsPossible    schedule 03.03.2011    source источник
comment
также интересно, как вернуть 401. Хотя ваше решение работает для меня, ни один из ответов мне не помог.   -  person Walter Luszczyk    schedule 28.09.2018


Ответы (6)


Установка ответа будет означать, что действие не вызывается.

public override void OnActionExecuting(HttpActionContext actionContext)    
{ 
    actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
}

Однако, как уже говорилось в других ответах, аутентификация должна выполняться с помощью AuthorizeAttribute (документы для Web.API или для MVC).

person Odeyinka Olubunmi    schedule 04.08.2015
comment
Это, вероятно, вызовет перенаправление на предполагаемую страницу входа. Это может быть нежелательным поведением. - person David; 03.03.2017

В .net core 2.2, 3.0 и 3.1 и .net 5 приведенный ниже пример работает нормально.

public override void OnActionExecuting(ActionExecutingContext context)
{
  context.Result = new UnauthorizedObjectResult("user is unauthorized");
}
person Nafis Islam    schedule 06.08.2020
comment
Это действительно для .NET core 3.1. - person Chelsea Saffold; 02.09.2020

Ответ, что @OdeyinkaOlubunmi верен для веб-API или, в частности, System.Web.Http.Filters.ActionFilterAttribute, но его нельзя использовать для System.Web.Mvc.ActionFilterAttribute. AuthorizeAttribute и переопределение AuthorizeCore — хороший способ, но если вы используете пример @Vadim для GlobalFilter, вы получите следующую ошибку в стандартной конфигурации:

Ошибка HTTP 404.15 — не найдено. Модуль фильтрации запросов настроен на отклонение запроса, если строка запроса слишком длинная.

Это связано с тем, что /Login?ReturnUrl= по умолчанию будет добавлять новые значения до тех пор, пока строка запроса не вызовет исключение.

То, как я решил это для MVC, выглядит так:

public class DebugActionFilter : System.Web.Mvc.ActionFilterAttribute
{
  public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext actionContext)
  {
    actionContext.Result = new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
    return;
  }
}
person Ogglas    schedule 25.01.2018

Вы можете установить результат filterContext для страницы исключения следующим образом:

filterContext.Result = new RedirectResult("~/Error/Unauthorized");

Дополнительные сведения см. здесь в разделе Отмена. Выполнение фильтра

person nelson eldoro    schedule 27.09.2013

Возможно, вы захотите сделать его AuthorizeAttribute. Это автоматически установит результат как UnAuthorizedResult, плюс он имеет то преимущество, что запускается перед любыми другими фильтрами. В качестве альтернативы вы можете установить в качестве результата новый HttpUnauthorizedResult

public class SignInRequiredAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        return !Acme.Web.CurrentUser != null;
    }
}
person Vadim    schedule 03.03.2011

используя .net core 2.1, приведенные выше решения не сработали для меня, поэтому я попробовал это, и это сработало: -

 context.HttpContext.Response.StatusCode = 401;
 return;

если есть лучшие решения для .net core 2.1, я открыт для предложений

person Eassa Nassar    schedule 17.01.2019
comment
Просто используйте return RedirectToAction(Someactionname); Кстати, в версии 2.1 это this.ControllerContext.HttpContext.Response.StatusCode = 401; - person netfed; 16.02.2019