asp.net core web api項(xiàng)目添加自定義中間件的實(shí)現(xiàn)
前言
在asp.net core web api項(xiàng)目中,默認(rèn)提供了很多的中間件,比如訪問靜態(tài)文件中間件UseStaticFiles,跨域配置中間件UseCors,路由中間件UseRouting,身份驗(yàn)證中間件UseAuthentication。
那么如何添加一些自定義的中間件呢。
需求
現(xiàn)在有一個(gè)需求,我們的所有接口中都有一個(gè)
TimeSpan參數(shù),傳入的是當(dāng)前時(shí)間的時(shí)間戳,正常需要對(duì)時(shí)間戳進(jìn)行加密,然后在加一個(gè)統(tǒng)一的驗(yàn)證方法,只正常處理2分鐘以內(nèi)的請(qǐng)求,超時(shí)的請(qǐng)求不在處理,直接返回錯(cuò)誤代碼,這樣可以一定程度上保護(hù)我們的業(yè)務(wù)數(shù)據(jù)。
這時(shí)我們就可以添加一個(gè)自定義的中間件,對(duì)所有過來的請(qǐng)求先進(jìn)行時(shí)間戳校驗(yàn)處理,處理通過的再返回到業(yè)務(wù)邏輯正常處理,時(shí)間戳校驗(yàn)不通過的則直接返回錯(cuò)誤碼。
實(shí)現(xiàn)
接下來看實(shí)現(xiàn)。
為了演示,我還是新建一個(gè)空的asp.net core web api項(xiàng)目。然后調(diào)用WeatherForecastController下的Get方法來做測(cè)試。
然后添加一個(gè)類,為了簡(jiǎn)單點(diǎn),這個(gè)類就一個(gè)TimeSpan參數(shù)。
public class BaseRequest
{
public string TimeSpan { get; set; }
}
為了方便的使用中間件,我們希望可以直接在Program下的Main函數(shù)里直接調(diào)用。類似這樣。
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
//這里是自定義添加的中間件
app.UseRequestCheckMiddleware();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
Startup里添加原理一樣。
所以首先我需要添加一個(gè)ApplicationBuilder的擴(kuò)展方法。這樣才能調(diào)用方法一樣用.出來。
添加一個(gè)ApplicationBuilderExtension類。
public static class ApplicationBuilderExtension
{
public static IApplicationBuilder UseRequestCheckMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCheckMiddleware>();
}
}
在這個(gè)類里通過builder.UseMiddleware傳入一個(gè)實(shí)現(xiàn)類,就可以實(shí)現(xiàn)中間件添加的效果了,如果想添加多個(gè)自定義的中間件,可以繼續(xù)添加新的Use方法。
接下來重點(diǎn)就是RequestCheckMiddleware的實(shí)現(xiàn)。
public class RequestCheckMiddleware
{
private readonly RequestDelegate _next;
public RequestCheckMiddleware(RequestDelegate next)
{
_next= next;
}
public async Task InvokeAsync(HttpContext context)
{
HttpRequest request = context.Request;
//緩存下來允許多次讀取
request.EnableBuffering();
var reader = new StreamReader(request.Body, Encoding.UTF8);
string data = await reader.ReadToEndAsync();
// 重置流的位置以便后續(xù)中間件可以讀取
request.Body.Position = 0;
try
{
var inputJson = JsonSerializer.Deserialize<BaseRequest>(data);
// 假設(shè) BaseRequest.TimeSpan 是一個(gè) long 類型的 UNIX 時(shí)間戳
if (string.IsNullOrEmpty(inputJson.TimeSpan))
{
await HandleError(context, 500, "時(shí)間戳為空!");
return;
}
var requestTime = UnixTimeStampToDateTime(Convert.ToInt64(inputJson.TimeSpan));
if (DateTime.Now - requestTime > TimeSpan.FromMinutes(2))
{
await HandleError(context, 429, "超時(shí)請(qǐng)求!");
return;
}
await _next(context);
}
catch (Exception ex)
{
await HandleError(context, 400, $"處理請(qǐng)求失敗: {ex.Message}");
}
}
private async Task HandleError(HttpContext context, int statusCode, string message)
{
context.Response.StatusCode = statusCode;
var result = new { code = statusCode, message = message, result = new object() };
await context.Response.WriteAsync(JsonSerializer.Serialize(result));
}
private DateTime UnixTimeStampToDateTime(long unixTimeStamp)
{
// UNIX 時(shí)間戳轉(zhuǎn)換為 DateTime
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
dateTime = dateTime.AddSeconds(unixTimeStamp).ToLocalTime();
return dateTime;
}
}
這里有幾點(diǎn)可以解釋一下。
1、這里的主函數(shù)名必須是Invoke或者InvokeAsync,且入?yún)⑹?code>HttpContext。表示這是在請(qǐng)求管道中對(duì)請(qǐng)求進(jìn)行處理的中間件。
2、這里需要定義RequestDelegate的委托,因?yàn)樾枰诋?dāng)前邏輯處理完成后,還需要把請(qǐng)求傳遞到下一步。
3、request.Body默認(rèn)只能被讀取一次,為了傳遞到下一步依然有原模原樣的請(qǐng)求參數(shù),所以需要先對(duì)請(qǐng)求進(jìn)行緩存處理。讀取完成之后,需要把流的位置重置到開始。方便后面可以再次讀取請(qǐng)求內(nèi)容。
然后在Program里添加對(duì)應(yīng)中間件就行了。
//這里是自定義添加的中間件 app.UseRequestCheckMiddleware();
驗(yàn)證
最后來演示一下效果。
首先傳遞一個(gè)2分鐘內(nèi)正常的時(shí)間戳。

請(qǐng)求可以正常返回。
接著等一會(huì)吧,等時(shí)間戳過期。

到此這篇關(guān)于asp.net core web api項(xiàng)目添加自定義中間件的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)asp.net core web api中間件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
ASP.NET Core 數(shù)據(jù)保護(hù)(Data Protection 集群場(chǎng)景)下篇
這篇文章主要為大家再一次介紹了ASP.NET Core 數(shù)據(jù)保護(hù)(Data Protection),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
寫一個(gè)含數(shù)字,拼音,漢字的驗(yàn)證碼生成類
本文和大家分享的是一個(gè)集成1:小寫拼音;2:大寫拼音;3:數(shù)字;4:漢字的驗(yàn)證碼生成類。本章例子也會(huì)有一個(gè)mvc使用驗(yàn)證碼校驗(yàn)的場(chǎng)景。具有一定的參考價(jià)值,下面跟著小編一起來看下吧2017-01-01
Asp.Net平臺(tái)下的圖片在線裁剪功能的實(shí)現(xiàn)代碼(源碼打包)
最近項(xiàng)目中有個(gè)圖片在線裁剪功能,本人查找資料,方法如下:前臺(tái)展現(xiàn)用jquery.Jcrop實(shí)現(xiàn),后臺(tái)使用 System.Drawing.Image類來進(jìn)行裁剪2011-10-10
ASP.NET C#生成下拉列表樹實(shí)現(xiàn)代碼
下拉列表樹很方便且時(shí)尚的一個(gè)導(dǎo)航,貌似很多的朋友都想實(shí)現(xiàn)這樣一個(gè)列表樹,本文將滿足你們的設(shè)想,通過本文你們可以學(xué)到如何使用c#生成下拉列表樹,感興趣的你可不要錯(cuò)過了啊2013-02-02
發(fā)布一個(gè)基于TokyoTyrant的C#客戶端開源項(xiàng)目
目前在網(wǎng)上關(guān)于TokyoCabinet(以下簡(jiǎn)稱TC)和TokyoTyrant(以下簡(jiǎn)稱TT)的資料已相對(duì)豐富了,但在.NET平臺(tái)上的客戶端軟件卻相對(duì)匱乏,因?yàn)樽鯠iscuz!NT企業(yè)版的關(guān)系,兩個(gè)月前開始接觸TC和TT,開始寫相關(guān)的客戶端代碼。2010-07-07
asp.net 定時(shí)間點(diǎn)執(zhí)行任務(wù)的簡(jiǎn)易解決辦法
這里的定時(shí)間點(diǎn)執(zhí)行任務(wù),指的是每天的某個(gè)時(shí)間執(zhí)行一項(xiàng)任務(wù)。2009-12-12
.Net使用SuperSocket框架實(shí)現(xiàn)WebSocket后端
這篇文章介紹了.Net使用SuperSocket框架實(shí)現(xiàn)WebSocket后端,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01

