65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.70/5 (23投票s)

2013年9月7日

CPOL

4分钟阅读

viewsIcon

121198

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

目录

  1. 引言
  2. ASP.NET MVC 中的过滤类型
  3. 对 Action Filter 的简单理解
  4. 使用代码 [Action Filter 类型,使用 Filter 进行授权,异常处理]
  5. 结论

引言

以前,我们使用传统的 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,因此如果我们能采取上述任何一种方法,那么整个应用程序的行为都将是安全的,或者是一个全局异常处理程序。

对于控制器,所有控制器已经具有上述四种类型的过滤器,因为它实现了 IActionFilterIResultFilterIAuthorizationFilterIExceptionFilter。 因此,我们可以覆盖 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 类继承了 ActionFilterAttributeActionFilterAttribute 类实现了 IActionFilter 接口。

结论

通过使用上述方法,不需要一次遵循不同的方法。 我建议编写您自己的过滤类并全局注册它。 我这里没有提到的一件事是“如何为 WebAPI 和 AJAX 进行异常和授权处理”。 本文的下一部分将讨论这个主题。 但是如果您的要求像上面的场景一样,那么您可以按照这种方式操作。 没有什么比处理授权和异常处理更聪明的方法了。

© . All rights reserved.