조치 필터 속성에서 경로 재 지정


139

어떤 것은에서 리디렉션을 할 수있는 가장 좋은 방법입니다 ActionFilterAttribute. I는있다 ActionFilterAttribute라고 IsAuthenticatedAttributeFilter하고는 세션 변수의 값을 확인. 변수가 false이면 응용 프로그램이 로그인 페이지로 리디렉션되도록하고 싶습니다. 경로 이름을 사용하여 리디렉션하는 것을 선호 SystemLogin하지만이 시점의 모든 리디렉션 방법이 좋습니다.


답변:


187

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

8
이것은 작동하지만 사용 가능한 RedirectToAction 메소드가 없어야합니까?
벤 밀스

그러나 @BenMills protected는 필터에서 액세스 할 수 없습니다.
James

10
내 질문은 이제 Microsoft 가이 필터를 protected합리적인 설명이 있어야 하기로 결정한 이유는 무엇입니까? RedirectToAction처음에 캡슐화 된 이유를 이해하지 못하고이 접근성을 재정의하는 것은 매우 더러운 느낌 입니다.
Matthew Marlin

2
@MatthewMarlin-액션으로 리디렉션하기위한 올바른 답변은 Syakur의 답변을 참조하십시오. 조치 필터에서 컨트롤러를 직접 호출해서는 안됩니다. 즉, 타이트 커플 링의 정의입니다.
NightOwl888

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

25
actionContext.Result.ExecuteResult액션 필터 내에서 호출하면 안됩니다. MVC는 액션 필터가 실행 된 후 자동으로이를 수행합니다 (제공된 actionContext.Result경우 null이 아님).
NightOwl888

12

MVC4를 사용하고 있는데 권한 부여 위반시 다음 방법을 사용하여 사용자 지정 HTML 화면을 리디렉션합니다.

확장 AuthorizeAttributeCutomAuthorizer 에 우선 OnAuthorization하고HandleUnauthorizedRequest

등록 CustomAuthorizerRegisterGlobalFilters.

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. 그렇다면 ActionFilterAttributeASP.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"클래스에서 상속하도록 모든 컨트롤러를 변경하는 것입니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.