ASP.NET MVC 中用于授权和异常处理的简单 Action Filter 概述






4.70/5 (23投票s)
ASP.NET MVC 中用于授权和异常处理的简单 Action Filter 概述。
目录
- 引言
- ASP.NET MVC 中的过滤类型
- 对 Action Filter 的简单理解
- 使用代码 [Action Filter 类型,使用 Filter 进行授权,异常处理]
- 结论
引言
以前,我们使用传统的 try..catch 块或在 ASP.NET 中全局 catch 异常。 ASP.NET 也有几种传统的方式来处理授权,比如用户信息的会话存储等等。但在 ASP.NET MVC 中,有一个更智能的方法,通过在通过控制器请求 Action 时使用过滤来处理授权和异常处理能力。 我将描述一个 ASP.NET MVC 应用程序的实际实现,以实现授权和异常处理。 最后,我还会讨论 ASP.NET MVC 过滤的基本原理。
ASP.NET MVC 中的过滤类型
ASP.NET 有一个很棒的功能:对 Action 的请求过滤。所有过滤器都在 Action Invoker 开始到执行过程结束时工作,这意味着在将处理后的数据发送给客户端之前。 Action Filter 有四种类型
- 授权过滤器:要授权请求,我们可以在 Global.asax 中添加过滤器对象。此过滤器需要实现的接口是 IAuthorizationFilter。
- Action Filter:如果要使用此过滤器,将实现 IActionFilter。
- Result Filter:这是对数据(传入和传出)非常重要的过滤,因为它有两个事件,它们在调用 Action 之前和之后触发。 我们将不得不实现 IResultFilter。
- ExceptionFilter:实现- IExceptionFilter属性,我们可以- catch任何异常并进一步处理。
Using the Code
例如,您正在开发一个 ASP.NET MVC 应用程序,但尚未实现安全性和异常处理机制。 因此,您将不得不实现这些,最好的方法是针对单个控制器或全局地针对所有控制器进行 Action 过滤,或者注册一个过滤器属性,以便所有 Action 都通过过滤过程。 我们知道,ASP.NET MVC 的入口点是通过控制器的 Action,因此如果我们能采取上述任何一种方法,那么整个应用程序的行为都将是安全的,或者是一个全局异常处理程序。
对于控制器,所有控制器已经具有上述四种类型的过滤器,因为它实现了 IActionFilter、IResultFilter、IAuthorizationFilter 和 IExceptionFilter。 因此,我们可以覆盖 OnAuthorization/ OnExecuting 进行授权,以及 OnException 进行异常处理。 但是我们必须为应用程序的所有控制器单独编写。
另一方面,我们可以通过继承 Controller 类并覆盖这些上述事件来进行授权和异常处理,创建一个 BaseController。 然后,每个控制器都必须继承 BaseController 而不是标准的 MVC 控制器,以便每个 Action 都通过过滤过程。
public class BaseController : Controller
{
    protected void SetAuthInfo(Guid Id, string Email, string FullName, string Role)
    {
        AuthUtil.SetAuthInfo(Id, Email, FullName, Role);
    }
    protected override void OnException(ExceptionContext filterContext)
    {
        //write your custom code here
    }
    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        //write your custom code here
    }
}
public class Home:BaseController
{
    public ActionResult Index()
    {
        return View();
    }  
}    
另一种方法是编写一个类并将其注册到 global.asax。 添加一个用于授权的类并全局注册
public class LogOnAuthoRization: AuthorizeAttribute
{     
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        var isAuthorised = base.IsAuthorized(actionContext);
        if (isAuthorised)
        {
            var cookie = HttpContext.Current.Request.Cookies
            [FormsAuthentication.FormsCookieName];
            var ticket = FormsAuthentication.Decrypt(cookie.Value);
            var identity = new GenericIdentity(ticket.Name);
            string userData = ticket.UserData;
            if (userData.Contains("_"))
            {
                string[] data = userData.Split('_');
                if (data != null && data.Length > 3)
                {
                    string Email = data[0];
                    string Id = data[1];
                    string FullName = data[2];
                    string Role = data[3];
                    var principal = new CustomUserPrincipal
                    (identity, new Guid(Id), Email, Role, FullName);
                    HttpContext.Current.User = principal;
                    Thread.CurrentPrincipal = principal;
                }
            }
        }
    }
} 
public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new CPExceptionHandler());
        filters.Add(new LogonAuthorizeAttribute());            
    }
    internal static void RegisterHttpFilters(System.Web.Http.Filters.HttpFilterCollection filters)
    {
        filters.Add(new APIAuthorizeAttribute());       
    }
} 
在 Application_Start 方法中注册 global.asax。
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
对于异常处理,您必须遵循上述方法。 但对于异常,您需要通过继承 HandleErrorAttribute 来编写一个类(如果您想全局注册而不是 BaseController 或单个控制器方法)。 稍后,您必须通过在 Application_Start 方法中调用 FilterConfig.RegisterGlobalFilters 来注册。 用于 Exception 处理的类将如下所示
public class CPExceptionHandler : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        //redirect to error page and do your necessary task here
    }
} 
您已经在之前的代码块中看到了我注册了“CPExceptionHandler”这个类作为全局过滤器。
有时我们需要根据 Action 的行为执行特定任务。 例如,如果网站所有者希望立即知道用户何时访问特定视图。 那么所有者希望从应用程序自动收到邮件。 对于这种类型的情况,我们可以使用 Action Filter。 执行 Action 后,应用程序将生成一封邮件并自动发送给所有者。
public class MyActivityFilter : ActionFilterAttribute{
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
  }
   public override void OnActionExecuted(ActionExecutedContext filterContext)
   {
    Task.Factory.StartNew(() => Email(filterContext));
   }
  public override void OnResultExecuting(ResultExecutingContext filterContext)
   {
   }
  public override void OnResultExecuted(ResultExecutedContext filterContext)
  {
  }
}
在上面的代码中,MyActivityFilter 类继承了 ActionFilterAttribute。 ActionFilterAttribute 类实现了 IActionFilter 接口。
结论
通过使用上述方法,不需要一次遵循不同的方法。 我建议编写您自己的过滤类并全局注册它。 我这里没有提到的一件事是“如何为 WebAPI 和 AJAX 进行异常和授权处理”。 本文的下一部分将讨论这个主题。 但是如果您的要求像上面的场景一样,那么您可以按照这种方式操作。 没有什么比处理授权和异常处理更聪明的方法了。

