[C# 강좌 - 68] MVC Framework filter 설정하기


Study/C#  2019. 7. 2. 09:00

안녕하세요. 명월입니다.


이 글은 C#의 MVC Framework에서 Filter에 대한 설명입니다.


C#의 MVC Framework 설치와 사용법에 대해 설명했습니다.

링크 - [C# 강좌 - 67] MVC Framework 프로젝트 생성하기


C#에서는 FilterAttribute를 이용해서 로그인 인증과 기타 공통 제어를 할 수 있습니다. 예를 들면 우리가 웹 사이트를 접속하면서 로그인 화면 이외에는 모든 페이지에 로그인 상태인지 아닌지 확인하고 로그인 상태가 아니면 로그인 화면으로 전환해야 합니다.

그것을 각 MVC에서 시작하는 모든 Action 메서드 위의 시작 부분에 호출하는 것도 하나의 방법이기는 하지만 좀 폼나게 프로그램답게 사용하는 방법이 있는데 그것이 필터입니다.


필터의 종류에는 Action 필터와 인증 필터가 있습니다. 먼저 인증 필터에 대해 설명하겠습니다.

먼저 인증 필터를 만들겠습니다.


디렉토리 구조에서 Common 폴더를 하나 생성해서 「AuthorizeFilter」라는 클래스를 생성했습니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVCExample.Common
{
  public class AuthorizeFilter : AuthorizeAttribute
  {
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
      // 파라미터로부터 http Context 데이터를 얻는다.
      HttpContextBase httpContext = filterContext.HttpContext;
      // 세션이 null 이면, 즉, 로그인 상태가 아니라면 redirect로 /Home/Logout으로 이동한다.
      if (httpContext.Session["USER"] == null)
      {
        httpContext.Response.Redirect("/Home/Logout");
        return;
      }

      // Filter Role이 Test의 경우는 통과한다.
      if ("TEST".Equals(Roles))
      {
        return;
      }
      else
      {
        // Filter Role이 Test가 아닌 경우 http code 401를 내보낸다.
        filterContext.Result = new HttpStatusCodeResult(401);
      }
    }
  }
}

그리고 AuthorizeAttribute의 클래스를 상속 받습니다. 사실 인증 필터에 대해서는 여러가지 사용 방법이 있어서 꼭 제가 하는 방식은 정답은 아닙니다만, 저의 경우는 이렇게 사용한다라고 이해하면 됩니다.

보통은 「AuthorizeCore」의 클래스를 override해서 사용하는 방법이 가장 일반적입니다만, 저의 경우는 OnAuthorization를 override해서 사용합니다.


어느 쪽이든 결과는 비슷합니다만 OnAuthorization가 AuthorizeCore보다 좀 더 빨리 호출되고(OnAuthorization -> AuthorizeCore -> OnAuthorization 순으로 호출됩니다.)무엇보다 http result code를 제어할 수 있어서 저는 AuthorizeCore메서드 보다 다루기가 더 편해서 OnAuthorization 메서드를 사용합니다.

[AuthorizeFilter]
public ActionResult About()
{
  return View();
}

HomeController에서 About 페이지를 들어가면 인증 필터를 확인하여 User 세션이 Null이면(당연히 세션엔 아무것도 넣은 적이 없기 때문에 null이 나옵니다.) Logout으로 Redirect하는 함수를 실행할 것입니다.

위 결과 페이지를 보면 Home/About을 들어갔으나 User 세션이 null이다 보니 Logout으로 redirect되는 것이 보이네요. 이 필터를 이용해서 로그인 세션 체크를 하고 로그인이 되어 있지 않으면 로그 아웃 페이지로 이동되는 Filter를 만들 수 있습니다.


두번째 Action 필터입니다. 사실 인증 필터의 역할도 이 Action 필터를 사용할 수 있습니다. 그러나 이 Action 필터는 인증을 필터하기 용도보다는 Controller의 공통 처리등을 담당하는 이벤트라고 생각하면 됩니다.

먼저 Action 필터를 만들곘습니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVCExample.Common
{
  public class ActionFilter : ActionFilterAttribute
  {
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
      filterContext.Controller.ViewBag.Data += "OnActionExecuting   ";
      base.OnActionExecuting(filterContext);
    }
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
      filterContext.Controller.ViewBag.Data += "OnActionExecuted   ";
      base.OnActionExecuted(filterContext);
    }
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
      filterContext.Controller.ViewBag.Data += "OnResultExecuting   ";
      base.OnResultExecuting(filterContext);
    }
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
      filterContext.Controller.ViewBag.Data += "OnResultExecuted   ";
      base.OnResultExecuted(filterContext);
    }
  }
}

ActionFilter의 경우는 「ActionFilterAttribute」 클래스를 상속받습니다. ActionFilterAttribute의 클래스는 4개의 이벤트가 존재하는 데 위 소스와 같이 OnActionExecuting, OnActionExecuted, OnResultExecuting, OnResultExecuted 가 있습니다.

[ActionFilter]
public ActionResult Contact()
{
  ViewBag.Data += "Action     ";
  return View();
}
@{
  ViewBag.Title = "Contact";
}
<h3>@ViewBag.Data</h3>

흐름에 대해서는 /Home/Contact url로 웹 브라이져를 치고 들어가면 먼저 ActionFilter의 OnActionExecuting가 호출됩니다. 두번 째는 Controller의 Action 메소드가 실행되고, 실행이 끝나면 필터의 OnActionExecuted가 호출됩니다.

그리고 다시 OnResultExecuting가 호출되고 View에서 설정한 cshtml파일을 읽어 오고 최종적으로 OnResultExecuted가 호출됩니다.

결과를 봐도 그런 흐름으로 ViewBag.Data가 만들어 졌습니다. 참고로 제일 마지막인 OnResultExecuted 표시되지 않았는데 이유는 OnResultExecuting가 호출되고 cshtml을 읽어 올 때 이미 html 파일의 형식이 완성이 되었기 때문에 ViewBag에 데이터를 넣어봤자 html파일이 변하지 않는 것입니다.

Action 필터의 경우는 모든 공통 처리를 하는 것으로 Action이 호출 되지 전의 처리 후의 처리 View의 호출되기 전의 처리 후의 처리를 나누어서 공통 처리를 하게 되면 Filter 클래스의 목적에 대해 정확하게 사용되는 것일 것입니다.


여기까지 C#에서 MVC Framework의 filter 사용하는 방법에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.