ASP.NET Core 練習 - 用 Middleware 為 Minimal API 加上 API Key 檢查
2 |
我很常寫小服務協助手工作業自動化,這類簡單 Web API 許多程式碼不過一百多行,連寫帶測半天就能寫完,沒啥必要切介面拆模組裝 Swagger 走 OpenAPI,網站框架也愈精簡愈好。因此 .NET Framework 時代我酷愛 NancyFX,而 ASP.NET Core 6.0 推出的 Minimal API,最短四行就寫好一個動態網頁,更是深得我心。
Side Project 有個資料服務需要識別呼叫來源,我想到最簡單的方法是在 HTTP 請求夾帶 API Key Header,執行動作前檢查正確再放行。當然,若求嚴謹可考慮 JWT Token 等正規做法(實作方法可參考保哥這篇:如何在 ASP.NET Core 6 使用 Token-based 身份認證與授權 (JWT)),居家自用小程式我偏好 Keep It Simple and Stupid,生個 GUID 當 API Key 應該就很夠了)
要檢查 Http Header,笨但可行的方法是寫個檢查 Header 函式,在執行動作前檢查,例如:
bool chkXApiHeader(HttpRequest request) =>
!request.Headers.TryGetValue(apiKeyHeaderName, out var apiKey)
|| apiKey != apiKeyValue;
app.Get("/api/action1", (context) => {
if (!chkXApiHeader(context.Request))
return Results.Unauthorized;
//... api logic
});
app.Get("/api/action2", (context) => {
if (!chkXApiHeader(context.Request))
return Results.Unauthorized;
//... api logic
});
一堆複製貼上的程式碼肯定不 OK 啊! Minimal API 不像 ASP.NET MVC 可以掛 Authorization Filter,但不要緊,回歸 ASP.NET Core 底層運作,我們有 Middleware 可在網頁處理流程加入各式自訂邏輯,本次的小任務將溫習 ASP.NET Core 基礎 - Middleware,為 Minimal API 加入 Header 檢查:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var apiKeyHeaderName = "X-Api-Key";
var apiKeyValue = app.Configuration["ApiKey"];
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments("/api"))
{
// 亦可限定來源 IP 提高安全性
// var ip = context.Connection.RemoteIpAddress.ToString();
if (!context.Request.Headers.TryGetValue(apiKeyHeaderName, out var apiKey)
|| apiKey != apiKeyValue)
{
context.Response.StatusCode = 401;
return context.Response.WriteAsync("Unauthorized");
}
}
return next();
});
app.MapGet("/", () => "Dummy WebAPI");
app.MapGet("/api/new-guid", () => Guid.NewGuid());
app.MapGet("/api/get-random", () => new Random().Next());
app.Run();
寫段 PowerShell 程式驗證,呼叫 / 不需附 X-Api-Key Header,呼叫 /api/new-guid 未附 X-Api-Key Header 或給錯值會得到 HTTP 401,附加正確的 X-Api-Key 才能呼叫成功!
(Invoke-WebRequest http://localhost:5174/).Content
try {
(Invoke-WebRequest http://localhost:5174/api/new-guid).Content
}
catch {
$_.Exception
}
try {
Invoke-WebRequest http://localhost:5174/api/new-guid -Headers @{ 'X-Api-Key' = 'WrongKey' }
}
catch {
$_.Exception
}
(Invoke-WebRequest http://localhost:5174/api/new-guid -Headers @{ 'X-Api-Key' = 'CorrectKey' }).Content
Exmaple of using middleware to check API key in ASP.NET Core minimal API.
Comments
# by HI
黑大 ASP.NET Core 基礎 - Middleware的網址錯囉 應該是這個 https://blog.darkthread.net/blog/aspnetcore-middleware-lab/
# by Jeffrey
to HI, 謝謝,已修正。