1) 생성자를 통해 next 객체 주입받고 , 처리 완료 후 next(context) 마지막에 호출 (RequestDeletegate next ) 2) Invoke 또는 InvokeAsync 메서드 만들기 public asyncTaskInvokeAsync(HttpContext context) { } 없으면 예외발생, InvalidOperationException: No public ‘Invoke’ or ‘InvokeAsync’ method found for middleware of type 3) startup.cs 에 미들웨어 등록하기 app.UseMiddleware<MYMIDDLEWARE>(); 이때 invoke 또는 invokeAsync 를 찾음
ㆍ 미들웨어 기본구조 & 미들웨어 등록
ㆍ 사용자 미들웨어 기본 구성 public class MyMiddleware { private readOnly RequestDelegate_next;
// 생산자를 통한 의존성 주입 public MyMiddleware(RequestDelegatenext) { this._next= next; }
// app.UseMiddleware() 로 호출시 Invoke 또는 InvokeAsync 함수를 찾는다. // 함수가 없으며, InvalidOperationException 예외발생 public AsyncTaskInvokeAsync(HttpContext context) { // 처리 await this._next(context); } }
MyAPIAuthMiddleware.cs ———————————————————————————————————————————————————- public class MyAPIAuthMiddleware { private const string KeyName = “APIKEY”; private readonly RequestDelegate _next; private readOnly IConfiguration _configuration;
public MyAPIAuthMiddleware(RequestDelegate next , IConfiguration configuration) { this._next = next; this._configuration = configuration; } public async Task InvokeAsync(HttpContext contenxt) { string serverKeyFromDI ; string serverKeyFromService ; string clientKey;
// 요청헤더로부터 클라이언트가 , true or false 그리고 key 값은 outAPIKey 에 할당 if (!context.Request.Headers.TryGetValue(KeyName , out val outAPIKey)) { await context.Response.WriteyAsync(“client API key empty”); return; }
clientKey = outAPIKey.toString().Trim();
// 1) 생성사 의존성 주입으로 받은 IConfiguration 으로 가져오기 string serverKeyFromDI = configuration[“API:Key”].toString();
// 2) DI 로 등록된 객체 RequestService.GetRequiredService<T> 로 IConfiguration 불러오기 var appSetting = context.RequestService.GetRequiredService<IConfiguration>(); string serverKeyFromService = appSetting.getValue<string>(“API:Key”);
// 정상적으로 처리되어 다음 미들웨어 호출함(현재 context 를 인자로), await this._next(context); } }
※ context.Response.WriteyAsync(); 처리 후 반드시 return 처리 next() 호출 안되게 해야됨 WriteAsync() 로 이미 응답한상태에서, 다른 미들웨어 또는 함수를 통해 다시 응답함으로써, 응답 헤더를 다시쓰면서 발생하는오류로 보임 CONNECTION_RESET 클라이언트 오류발생함그러므로 , 요청에 응답처리를 했을경우 반드시 return; 을 통해 next() 함수가 호출되지 않게해야한다. (단, 오류가 없이 응답헤더를 작성하지 않았다면 next() 로 정상호출)
정리, 사용자 Middleware 를 통해 WebAPI 인증을 거치기 위해서는 먼저 Middleware in asp.net Core 에서 Middleware 작성 하는 방법을 알아보자.attribute 보다 간단하고, 명료하다.일전에 attribute 를 통해 WebAPI 를 인증하듯, client 의 요청 헤더를 읽어 요청하는 API 키를 가져온다거나 IConfiguration 을 통해 appSetting.json 서버키를 가져오는 로직등은 똑같다.
단, 파이프라인으로 구성된 Middleware 에서는 내가 만든 사용자 Middleware 실행 후 다음 Middleware 를 실행하지 않으면 Middleware 가 단락되므로, 반드시 다음 Middleware 실행을 위해 RequestDelete 를 주입받아, 정상적으로 인증(처리가) 완료되면 next() 호출을 반드시 해줘야 하며, 만약 인증오류 및 조건에 부합하지 않는다면, 직접 Resopnse.WriteAsync() 를 출력하여 사용자에게 메세지를 보내고,, 반드시 return; 시켜, next() 를 호출 하지 않게 해야한다.
만약, Response.writeAysnc() 를 통해 메세지를 출력하고, next() 호출하게되면::CONNECTION_RESET javascript 오류가발생하고 출력도안되는 현상이 발생한다.이는 Attribute 작성시 next() 호출할때 (여기서 next() 는 미들웨어의 next 와 달리 attribute 를 호출한 클래스나, 메서드 , 인터페이스 를 호출하는 next() 임) context.Result(Content, content-type , StatusCode)가 Null 이 아닐때 오류가 발생하는것과 비슷한것같다.