一、Filter的开辟和挪用
在默许的WebApi中,框架供应了三种Filter,他们的功用和运转前提以下表所示:
Filter 范例 |
完成的接口 |
形貌 |
Authorization |
IAuthorizationFilter |
最早运转的Filter,被用作请求权限校验 |
Action |
IActionFilter |
在Action运转的前、后运转 |
Exception |
IExceptionFilter |
当异常发作的时刻运转 |
起首,我们完成一个AuthorizatoinFilter可以用以简朴的权限掌握:
(actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute> verifyResult = actionContext.Request.Headers.Authorization!= && == ; (!= HttpError(
一个简朴的用于用户考证的Filter就开辟完了,这个Filter请求用户的请求中带有Authorization头而且参数为123456,假如经由过程则放行,不经由过程则返回401毛病,并在Content中提醒Token不正确。下面,我们须要注册这个Filter,注册Filter有三种要领:
第一种:在我们愿望举行权限掌握的Action上打上AuthFilterAttribute这个Attribute:
public class PersonController : ApiController { [AuthFilter] public CreateResult Post(CreateUser user) { return new CreateResult() {Id = "123"}; } }
这类体式格局合适单个Action的权限掌握。
第二种,找到相应的Controller,并打上这个Attribute:
[AuthFilter] public class PersonController : ApiController { public CreateResult Post(CreateUser user) { return new CreateResult() {Id = "123"}; } }
这类体式格局合适于掌握全部Controller,打上这个Attribute今后,全部Controller里一切Action都获得了权限掌握。
第三种,找到App_Start\WebApiConfig.cs,在Register要领下到场Filter实例:
{ id =
用这类体式格局合适于掌握一切的API,恣意Controller和恣意Action都接受了这个权限掌握。
在大多数场景中,每一个API的权限考证逻辑都是一样的,在如许的前提下运用全局注册Filter的要领最为简朴便利,可如许存在一个不言而喻的题目:假如某几个API是不须要掌握的(比方登录)怎么办?我们可以在如许的API上做如许的处置惩罚:
[AllowAnonymous]public CreateResult PostLogin(LoginEntity entity) { //TODO:增加考证逻辑 return new CreateResult() {Id = "123456"}; }
我为这个Action打上了AllowAnonymousAttribute,考证逻辑就放过了这个API而不举行权限校验。
在现实的开辟中,我们可以设想一套相似Session的机制,经由过程用户登录来猎取Token,在以后的交互HTTP请求中加上Authorization头并带上这个Token,并在自定义的AuthFilterAttribute中对Token举行考证,一套规范的Token考证流程就可以完成了。
接下来我们引见ActionFilter:
ActionFilterAttrubute供应了两个要领举行阻拦:OnActionExecuting和OnActionExecuted,他们都供应了同步和异步的要领。
OnActionExecuting要领在Action实行之前实行,OnActionExecuted要领在Action实行完成以后实行。
我们来看一个运用场景:运用过MVC的同砚肯定不生疏MVC的模子绑定和模子校验,运用起来异常轻易,定义好Entity以后,在须要举行校验的处所可以打上相应的Attribute,在Action开始时搜检ModelState的IsValid属性,假如校验不经由过程直接返回View,前端可以剖析并显现未经由过程校验的缘由。而Web API中也继续了这一轻易的特征,运用起来越发轻易:
public class CustomActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { if (!actionContext.ModelState.IsValid) { actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState); } } }
这个Filter就供应了模子校验的功用,假如未经由过程模子校验则返回400毛病,并把相干的毛病信息交给挪用者。他的运用要领和AuthFilterAttribute一样,可以针对Action、Controller、全局运用。我们可以用下面一个例子来考证:
代码以下:
public class LoginEntity { [Required(ErrorMessage = "缺乏用户名")] public string UserName { get; set; } [Required(ErrorMessage = "缺乏暗码")] public string Password { get; set; } }
[AllowAnonymous] [CustomActionFilter]public CreateResult PostLogin(LoginEntity entity) { //TODO:增加考证逻辑 return new CreateResult() {Id = "123456"}; }
固然,你也可以依据本身的须要剖析ModelState然后用本身的花样将毛病信息经由过程Request.CreateResponse()返回给用户。
OnActionExecuted要领我在现实工作中运用得较少,现在仅在一次部份相应数据加密的场景下举行过运用,运用要领一样,读取已有的相应,并加密后再给出加密后的相应赋值给actionContext.Response即可。
我给人人一个Demo:
public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) { var key = 10; var responseBody = await actionExecutedContext.Response.Content.ReadAsByteArrayAsync(); //以Byte数组体式格局读取Content中的数据 for (int i = 0; i < responseBody.Length; i++) { responseBody[i] = (byte)(responseBody[i] ^ key); //对每一个Byte做异或运算 } actionExecutedContext.Response.Content = new ByteArrayContent(responseBody); //将效果赋值给Response的Content actionExecutedContext.Response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("Encrypt/Bytes"); //并修正Content-Type}
经由过程这个要领我们将相应的Content每一个Byte都做了一个异或运算,对相应内容举行了一次简朴的加密,人人可以依据本身的须要举行更牢靠的加密,如AES、DES或许RSA…经由过程这个要领可以天真地对某个Action的处置惩罚后的效果举行处置惩罚,经由过程Filter举行相应内容加密有很强的天真性和通用性,他能猎取当前Action的许多信息,然后依据这些信息挑选加密的体式格局、猎取加密所需的参数等等。假如加密所运用参数对当前实行的Action没有依靠,也可以采用HttpMessageHandler来举行处置惩罚,在以后的教程中我会举行引见。
末了一个Filter:ExceptionFilter
望文生义,这个Filter是用来举行异常处置惩罚的,当营业发作未处置惩罚的异常,我们是不愿望用户接收到黄页或许其他用户没法剖析的信息的,我们可以运用ExceptionFilter来举行一致处置惩罚:
public class ExceptionFilter : ExceptionFilterAttribute { public override void OnException(HttpActionExecutedContext actionExecutedContext) { //假如截获异常为我们自定义,可以处置惩罚的异常则经由过程我们本身的划定规矩处置惩罚 if (actionExecutedContext.Exception is DemoException) { //TODO:纪录日记 actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse( HttpStatusCode.BadRequest, new {Message = actionExecutedContext.Exception.Message}); } else { //假如截获异常是我没没法预感的异常,则将通用的返回信息返回给用户,防止泄漏过量信息,也便于用户处置惩罚 //TODO:纪录日记 actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(HttpStatusCode.InternalServerError, new {Message = "服务器被外星人拐跑了!"}); } } }
我们定义了一个ExceptoinFilter用于处置惩罚未捕捉的异常,我们将异常分为两类:一类是我们可以预感的异常:如营业参数毛病,越权等营业异常;另有一类是我们没法预感的异常:如数据库衔接断开、内存溢出等异常。我们经由过程HTTP Code示知挪用者以及用相对牢固、友爱的数据结构将异常信息通知挪用者,以便于挪用者纪录并处置惩罚如许的异常。
[CustomerExceptionFilter]public class TestController : ApiController { public int Get(int a, int b) { if (a < b) { throw new DemoException("A必需要比B大!"); } if (a == b) { throw new NotImplementedException(); } return a*b; } }
我们定义了一个Action:在差别的情况下会抛出差别的异常,个中一个异常是我们可以预感并认为是挪用者传参失足的,一个是不可以处置惩罚的,我们看一下效果:
在如许的RestApi中,我们可以预先定义好异常的表现形式,让挪用者可以轻易地推断什么情况下是涌现异常了,然后经由过程较为一致的异常信息返回体式格局让挪用者轻易地剖析异常信息,构成一致轻易的异常音讯处置惩罚机制。
然则,ExceptionFilter只能在胜利完成了Controller的初始化今后才起到捕捉、处置惩罚异常的作用,而在Controller初始化完成之前(比方在Controller的组织函数中涌现了异常)则ExceptionFilter无计可施。对此WebApi引入了ExceptionLogger和ExceptionHandler处置惩罚机制,我们将在以后的文章中举行解说。
二、Filter的实行递次
在运用MVC的时刻,ActionFilter供应了一个Order属性,用户可以依据这个属性掌握Filter的挪用递次,而Web API却不再支撑该属性。Web API的Filter有本身的一套挪用递次划定规矩:
一切Filter依据注册位置的差别具有三种作用域:Global、Controller、Action:
经由过程HttpConfiguration类实例下Filters.Add()要领注册的Filter(平常在App_Start\WebApiConfig.cs文件中的Register要领中设置)就属于Global作用域;
经由过程Controller上打的Attribute举行注册的Filter就属于Controller作用域;
经由过程Action上打的Attribute举行注册的Filter就属于Action作用域;
他们遵照了以下划定规矩:
1、在统一作用域下,AuthorizationFilter最早实行,以后实行ActionFilter
2、关于AuthorizationFilter和ActionFilter.OnActionExcuting来讲,假如一个请求的生命周期中有多个Filter的话,实行递次都是Global->Controller->Action;
3、关于ActionFilter,OnActionExecuting老是先于OnActionExecuted实行;
4、关于ExceptionFilter和ActionFilter.OnActionExcuted而言实行递次为Action->Controller->Global;
5、关于一切Filter来讲,假如阻挠了请求:即对Response举行了赋值,则后续的Filter不再实行。
关于默许情况下的Filter相干学问我们就讲这么一些,假如在文章中有任何不正确的处所或许疑问,迎接人人为我指出。
以上就是Asp.Net WebAPI中 Filter的运用以及实行递次(珍藏)的细致内容,更多请关注ki4网别的相干文章!