iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0
Modern Web

擁抱 .Net Core系列 第 21

[Day20] 中介軟體 Middleware - 3

  • 分享至 

  • xImage
  •  

昨天提到了Middleware的使用方式,今天來看看其他的使用方式

基於約定的Middleware

所謂的基於約定有點像是鴨子型別的概念
當滿足約定的話,我們就能把它視為一個中介軟體
讓我們來看看一個符合中介軟體的約定有哪些

  1. 有一個參數為RequestDelegate類型的public 建構式
  2. 一個名為Invoke或InvoikeAsync且方法的第一個參數為HttpContext
    且回傳類型Task為的public方法

這是一個驗證http request是否為有效的middleware
細節我是隨便寫的,用了MD5所以不要直接call來用

public class SignatureMiddleware
{
    private readonly RequestDelegate _next;

    public SignatureMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    
    public async Task InvokeAsync(HttpContext context)
    {
        var request = context.Request;
        var response = context.Response;
        var buffer = new byte[Convert.ToInt32(request.ContentLength)];
        var _ = await request.Body.ReadAsync(buffer);
        var bodyAsText = Encoding.UTF8.GetString(buffer);
        request.Body = new MemoryStream(buffer);
        var signature = request.Headers["X-Signature"];
        var timestamp = request.Headers["X-Signature-Timestamp"];
        var isValid = Verify(bodyAsText, signature, timestamp);
        if (!isValid)
        {
            response.StatusCode = 401;
            return;
        }
        await _next.Invoke(context);
    }

    private static bool Verify(string body, string signature, string timestamp)
    {   
        var md5 = MD5.Create();
        var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(body + timestamp));
        var hashString = BitConverter.ToString(hash).Replace("-", "").ToLower();
        return hashString == signature;
    }
}

可以看到這個middleware滿足我所說的條件
然後可以在program.cs中依照想要的位置
使用app.UseMiddleware插入這個middleware

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseMiddleware<SignatureMiddleware>();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

await app.RunAsync();

**
另外基於約定的Middleware是應用程式啟動時即建立實體,他在某種程度上類似singleton
因此雨果要使用,其他註冊為Scope的服務並不能在建構式中注入
而要在Invoke方法中注入
**

public async Task InvokeAsync(HttpContext context, IMyService)
{
    // DoSomething
}

強型別的Middleware

除了這種基於約定的middleware外
也可以選擇實作IMiddleware
實作IMiddlewareMiddleware
是由IMiddlewareFactory所建立的
相比基於約定的中介軟體
他是

  • 強類型的
  • Scoped的,也就是可以透過建構式注入其他服務
public class SignatureMiddleware : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var request = context.Request;
        var response = context.Response;
        var buffer = new byte[Convert.ToInt32(request.ContentLength)];
        var _ = await request.Body.ReadAsync(buffer);
        var bodyAsText = Encoding.UTF8.GetString(buffer);
        request.Body = new MemoryStream(buffer);
        var signature = request.Headers["X-Signature-"];
        var timestamp = request.Headers["X-Signature-Timestamp"];
        var isValid = Verify(bodyAsText, signature, timestamp);
        if (!isValid)
        {
            response.StatusCode = 401;
            return;
        }
        await next.Invoke(context);
    }

    private static bool Verify(string body, string signature, string timestamp)
    {   
        var md5 = MD5.Create();
        var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(body + timestamp));
        var hashString = BitConverter.ToString(hash).Replace("-", "").ToLower();
        return hashString == signature;
    }
}

使用上基本上跟基於約定的Middleware相同

app.UseMiddleware<SignatureMiddleware>();

上一篇
[Day20] 中介軟體 Middleware - 2
下一篇
[Day22] 路由 Routing - 1
系列文
擁抱 .Net Core30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言