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 进行异常和授权处理”。 本文的下一部分将讨论这个主题。 但是如果您的要求像上面的场景一样,那么您可以按照这种方式操作。 没有什么比处理授权和异常处理更聪明的方法了。