In WEB Api wird die Idee der aspektorientierten Programmierung (AOP) eingeführt, und an bestimmten Stellen können bestimmte Filter für die Prozessabfangverarbeitung eingefügt werden. Durch die Einführung dieses Mechanismus kann die DRY-Idee (Don't Repeat Yourself) besser umgesetzt werden. Durch Filter können einige gängige Logiken einheitlich verarbeitet werden, z. B. Berechtigungsüberprüfung, Parameterverschlüsselung und -entschlüsselung, Parameterüberprüfung usw. Wir alle haben diese Funktion kann für eine einheitliche Verarbeitung verwendet werden. Heute stellen wir die Entwicklung und Verwendung von Filtern vor und diskutieren deren Ausführungssequenz.
1. Entwicklung und Aufruf von Filter
Im Standard-WebApi stellt das Framework drei Arten von Filtern bereit, wie in der folgenden Tabelle dargestellt :
Filter Filter 类型 实现的接口 描述 Authorization IAuthorizationFilter 最先运行的Filter,被用作请求权限校验 Action IActionFilter 在Action运行的前、后运行 Exception IExceptionFilter 当异常发生的时候运行 |
Implementierte Schnittstelle |
Beschreibung |
||||||||||||
Autorisierung | IAuthorizationFilter | Der erste, der ausgeführt wirdFilter, wird zum Anfordern einer Berechtigungsüberprüfung verwendet | tr>||||||||||||
Action | IActionFilter | InAktionVor und nach der Operation | ||||||||||||
Ausnahme | IExceptionFilter | Ausführen, wenn eine Ausnahme auftritt |
Zuerst implementieren wir einen Autorisierungsfilter, der zur einfachen Berechtigungskontrolle verwendet werden kann:
(actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute> verifyResult = actionContext.Request.Headers.Authorization!= && == ; (!= HttpError(
Ein einfacher Filter zur Benutzerüberprüfung wird entwickelt. Dieser Filter erfordert, dass die Benutzeranforderung den Autorisierungsheader enthält Der Parameter ist 123456. Wenn er erfolgreich ist, wird er freigegeben. Wenn er nicht erfolgreich ist, wird ein 401-Fehler zurückgegeben und es wird angezeigt, dass das Token im Inhalt falsch ist. Als nächstes müssen wir diesen Filter registrieren. Es gibt drei Möglichkeiten, einen Filter zu registrieren:
Die erste: Setzen Sie das AuthFilterAttribute auf die Aktion, die wir steuern möchten:
public class PersonController : ApiController { [AuthFilter] public CreateResult Post(CreateUser user) { return new CreateResult() {Id = "123"}; } }
Dies Geeignet für die Berechtigungskontrolle einer einzelnen Aktion.
Die zweite Methode besteht darin, den entsprechenden Controller zu finden und dieses Attribut hinzuzufügen:
[AuthFilter] public class PersonController : ApiController { public CreateResult Post(CreateUser user) { return new CreateResult() {Id = "123"}; } }
Diese Methode eignet sich zum Steuern des gesamten Controllers. Nach dem Hinzufügen dieses Attributs werden alle Aktionen im gesamten Controller hinzugefügt Zugangskontrolle erhalten wird.
Die dritte Methode besteht darin, App_StartWebApiConfig.cs zu finden und eine Filterinstanz unter der Register-Methode hinzuzufügen:
{ id =
Diese Methode eignet sich zur Steuerung aller APIs und wird von jedem Controller und jedem akzeptiert Aktion. Diese Berechtigungskontrolle.
In den meisten Szenarien ist die Berechtigungsüberprüfungslogik jeder API dieselbe. Unter dieser Voraussetzung ist es die einfachste und bequemste Methode, die globale Registrierung von Filtern zu verwenden. Es gibt jedoch ein offensichtliches Problem: wenn sicher Benutzer Was soll ich tun, wenn eine API keine Kontrolle erfordert (z. B. Anmeldung)? Wir können dies mit einer solchen API tun:
[AllowAnonymous]public CreateResult PostLogin(LoginEntity entity) { //TODO:添加验证逻辑 return new CreateResult() {Id = "123456"}; }
Ich habe „AllowAnonymousAttribute“ für diese Aktion markiert und die Verifizierungslogik hat diese API ignoriert, ohne eine Berechtigungsüberprüfung durchzuführen.
In der tatsächlichen Entwicklung können wir einen Mechanismus ähnlich der Sitzung entwerfen, um ein Token über die Benutzeranmeldung zu erhalten, den Autorisierungsheader hinzuzufügen und dieses Token in nachfolgende interaktive HTTP-Anforderungen einzubringen und anzupassen. Um das Token im AuthFilterAttribute zu überprüfen, a Es kann ein Standard-Token-Verifizierungsprozess implementiert werden.
Als nächstes stellen wir ActionFilter vor:
ActionFilterAttrubute bietet zwei Methoden zum Abfangen: OnActionExecuting und OnActionExecuted, die beide synchrone und asynchrone Methoden bereitstellen.
Die OnActionExecuting-Methode wird ausgeführt, bevor die Aktion ausgeführt wird, und die OnActionExecuted-Methode wird ausgeführt, nachdem die Aktion ausgeführt wird.
Schauen wir uns ein Anwendungsszenario an: Schüler, die MVC verwendet haben, müssen mit der Modellbindung und Modellüberprüfung von MVC vertraut sein. Nach der Definition der Entität können Sie sie dort markieren, wo eine Überprüfung erforderlich ist. Überprüfen Sie für das entsprechende Attribut das IsValid-Attribut des ModelState, wenn die Überprüfung fehlschlägt. Das Frontend kann den Grund für den Fehler der Überprüfung analysieren. Die Web-API erbt auch diese praktische Funktion, wodurch die Verwendung komfortabler wird:
public class CustomActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { if (!actionContext.ModelState.IsValid) { actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState); } } }
Dieser Filter bietet die Funktion der Modellüberprüfung. Wenn die Modellüberprüfung fehlschlägt, wird ein 400-Fehler zurückgegeben und ist relevant Fehlerinformationen an den Anrufer. Seine Verwendung ist die gleiche wie bei AuthFilterAttribute und kann für Action, Controller und global verwendet werden. Wir können das folgende Beispiel zur Überprüfung verwenden:
Der Code lautet wie folgt:
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"}; }
Natürlich können Sie den ModelState auch entsprechend Ihren eigenen Anforderungen analysieren und die Fehlerinformationen über Request.CreateResponse() in Ihrem eigenen Format an den Benutzer zurückgeben.
Ich verwende die OnActionExecuted-Methode in der tatsächlichen Arbeit nur selten. Die Verwendungsmethode ist dieselbe: Lesen Sie die vorhandene Antwort, verschlüsseln Sie sie und geben Sie sie dann weiter Weisen Sie einfach die verschlüsselte Antwort actionContext.Response zu.
Ich gebe Ihnen eine 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}
Mit dieser Methode führen wir eine XOR-Operation für jedes Byte des Antwortinhalts durch Der Inhalt wird einfach verschlüsselt, je nach Bedarf, wie AES, DES oder RSA. Mit dieser Methode können Sie das Ergebnis einer Aktion flexibel verarbeiten und über die Filterung reagieren und Vielseitigkeit. Es kann viele Informationen über die aktuelle Aktion abrufen, dann die Verschlüsselungsmethode basierend auf diesen Informationen auswählen, die für die Verschlüsselung erforderlichen Parameter abrufen und so weiter. Wenn die zur Verschlüsselung verwendeten Parameter keine Abhängigkeit von der aktuell ausgeführten Aktion haben, können Sie zur Verarbeitung auch HttpMessageHandler verwenden, den ich in einem nachfolgenden Tutorial vorstellen werde.
Der letzte 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相关知识我们就讲这么一些,如果在文章中有任何不正确的地方或者疑问,欢迎大家为我指出。
Das obige ist der detaillierte Inhalt vonDie Verwendung und Ausführungssequenz von Filter in Asp.Net WebAPI (Favorit). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!