聊一聊Asp.net过滤器Filter那一些事

最近在整理优化.net代码时,发现几个很不友好的处理现象:登录判断、权限认证、日志记录、异常处理等通用操作,在项目中的action中到处都是。在代码优化上,这一点是很重要着力点。这时.net中的过滤器、拦截器(Filter)就派上用场了。现在根据这几天的实际工作,对其做了一个简单的梳理,分享出来,以供大家参考交流,如有写的不妥之处,多多指出,多多交流。

概述:

.net中的Filter中主要包括以下4大类:Authorize(授权),ActionFilter(自定义),HandleError(错误处理)。

过滤器

 

类名

 

实现接口

 

描述

 

授权

 

AuthorizeAttribute

 

IAuthorizationFilter

 

此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法,比如:登录、权限、访问控制等等

 

异常

 

HandleErrorAttribute

 

IExceptionFilter

 

用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常,比如:全局异常统一处理。

 

自定义

 

ActionFilterAttribute

 

IActionFilter和IResultFilter

 

用于进入行为之前或之后的处理或返回结果的之前或之后的处理,比如:用户请求日志详情日志记录

 

AuthorizeAttribute:认证授权

认证授权主要是对所有action的访问第一入口认证,对用户的访问做第一道监管过滤拦截闸口。

实现方式:需要自定义一个类,继承AuthorizeAttribute并重写OnAuthorization,在OnAuthorization中能够获取到用户请求的所有Request信息,其实我们做的所有认证拦截操作,其所有数据支撑都是来自Request中。

具体验证流程设计:

IP白名单:这个主要针对的是API做IP限制,只有指定IP才可访问,非指定IP直接返回

请求频率控制:这个主要是控制用户的访问频率,主要是针对API做,超出请求频率直接返回。

登录认证:登录认证一般我们采用的是通过在请求的header中传递token的方式来进行验证,这样即使用与一般的MVC登录认证,也使用与API接口的Auth认证,并且也不依赖于用户前端js设置等。

授权认证:授权认证就简单了,主要是验证该用户是否具有该权限,如果不具有,直接做下相应的返回处理。

MVC和API异同:

  命名空间:MVC:System.Web.Http.Filters;API:System.Web.Mvc

  注入方式:在注入方式上,主要包括:全局->控制器Controller->行为Action

  全局注册:针对所有系统的所有Aciton都使用

  Controller:只针对该Controller下的Action起作用

  Action:只针对该Action起作用

其中全局注册,针对MVC和API还有一些差异:

  MVC在 FilterConfig.cs中注入

filters.Add(new XYHMVCAuthorizeAttribute());

API 在 WebApiConfig.cs 中注入

config.Filters.Add(new XYHAPIAuthorizeAttribute());

 注意事项:在实际使用中,针对认证授权,我们一般都是添加全局认证,但是,有的action又不需要做认证,比如本来的登录Action等等,那么该如何排除呢?其实也很简单,我们只需要在自定定义一个Attribute集成Attribute,或者系统的AllowAnonymousAttribute,在不需要验证的action中只需要注册上对于的Attribute,并在验证前做一个过滤即可,比如:

// 有 AllowAnonymous 属性的接口直接开绿灯 if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()) { return; }

API AuthFilterAttribute实例代码

/// <summary> /// 授权认证过滤器 /// </summary> public class XYHAPIAuthFilterAttribute : AuthorizationFilterAttribute { /// <summary> /// 认证授权验证 /// </summary> /// <param>请求上下文</param> public override void OnAuthorization(HttpActionContext actionContext) { // 有 AllowAnonymous 属性的接口直接开绿灯 if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()) { return; } // 在请求前做一层拦截,主要验证token的有效性和验签 HttpRequest httpRequest = HttpContext.Current.Request; // 获取apikey var apikey = httpRequest.QueryString["apikey"]; // 首先做IP白名单校验 MBaseResult<string> result = new AuthCheckService().CheckIpWhitelist(FilterAttributeHelp.GetIPAddress(actionContext.Request), apikey); // 检验时间搓 string timestamp = httpRequest.QueryString["Timestamp"]; if (result.Code == MResultCodeEnum.successCode) { // 检验时间搓 result = new AuthCheckService().CheckTimestamp(timestamp); } if (result.Code == MResultCodeEnum.successCode) { // 做请求频率验证 string acitonName = actionContext.ActionDescriptor.ActionName; string controllerName = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName; result = new AuthCheckService().CheckRequestFrequency(apikey, $"api/{controllerName.ToLower()}/{acitonName.ToLower()}"); } if (result.Code == MResultCodeEnum.successCode) { // 签名校验 // 获取全部的请求参数 Dictionary<string, string> queryParameters = httpRequest.GetAllQueryParameters(); result = new AuthCheckService().SignCheck(queryParameters, apikey); if (result.Code == MResultCodeEnum.successCode) { // 如果有NoChekokenFilterAttribute 标签 那么直接不做token认证 if (actionContext.ActionDescriptor.GetCustomAttributes<XYHAPINoChekokenFilterAttribute>().Any()) { return; } // 校验token的有效性 // 获取一个 token string token = httpRequest.Headers.GetValues("Token") == null ? string.Empty : httpRequest.Headers.GetValues("Token")[0]; result = new AuthCheckService().CheckToken(token, apikey, httpRequest.FilePath); } } // 输出 if (result.Code != MResultCodeEnum.successCode) { // 一定要实例化一个response,是否最终还是会执行action中的代码 actionContext.Response = new HttpResponseMessage(HttpStatusCode.OK); //需要自己指定输出内容和类型 HttpContext.Current.Response.ContentType = "text/html;charset=utf-8"; HttpContext.Current.Response.Write(JsonConvert.SerializeObject(result)); HttpContext.Current.Response.End(); // 此处结束响应,就不会走路由系统 } } }

MVC AuthFilterAttribute实例代码

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjfspx.html