GitHub demo https://github.com/zhanglilong23/Asp.NetCore.Demo
本項目使用中間件攔截請求數據,並對請求數據解密。 訪問接口成功後攔截返回數據,然後將返回數據加密後返回。
其中log4net部分不再贅述(demo中有介紹)
將Post方法中Body中的數據進行AES解密
將返回數據進行AES加密
1:自定義中間件,並默認實現Invoke方法. 附帶使用日誌記錄錯誤和訪問時間等,寫的比較糙。
public class HttpContextMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
/// <summary>
/// 計時器
/// </summary>
private Stopwatch _stopwatch;
//加密解密key
private readonly string securitykey = "0123456789abcdef";
/// <summary>
/// 構造 Http 請求中間件
/// </summary>
/// <param name="next"></param>
/// <param name="loggerFactory"></param>
/// <param name="cacheService"></param>
public HttpContextMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory.CreateLogger<HttpContextMiddleware>();
}
/// <summary>
/// 1:將Post方法中Body中的數據進行AES解密
/// 2:將返回數據進行AES加密
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task Invoke(HttpContext context)
{
context.Request.EnableBuffering();
_stopwatch = new Stopwatch();
_stopwatch.Start();
_logger.LogInformation($"Handling request: " + context.Request.Path);
var api = new ApiRequestInputViewModel
{
HttpType = context.Request.Method,
Query = context.Request.QueryString.Value,
RequestUrl = context.Request.Path,
RequestName = "",
RequestIP = context.Request.Host.Value
};
var request = context.Request.Body;
var response = context.Response.Body;
try
{
using (var newRequest = new MemoryStream())
{
//替換request流
context.Request.Body = newRequest;
using (var newResponse = new MemoryStream())
{
//替換response流
context.Response.Body = newResponse;
using (var reader = new StreamReader(request))
{
//讀取原始請求流的內容
api.Body = await reader.ReadToEndAsync();
if (string.IsNullOrEmpty(api.Body))
await _next.Invoke(context);
//示例加密字符串,使用 AES-ECB-PKCS7 方式加密,密鑰爲:0123456789abcdef
// 加密參數:{"value":"哈哈哈"}
// 加密後數據: oedwSKGyfLX8ADtx2Z8k1Q7+pIoAkdqllaOngP4TvQ4=
api.Body = SecurityHelper.AESDecrypt(api.Body, securitykey);
}
using (var writer = new StreamWriter(newRequest))
{
await writer.WriteAsync(api.Body);
await writer.FlushAsync();
newRequest.Position = 0;
context.Request.Body = newRequest;
await _next(context);
}
using (var reader = new StreamReader(newResponse))
{
newResponse.Position = 0;
api.ResponseBody = await reader.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(api.ResponseBody))
{
api.ResponseBody = SecurityHelper.AESEncrypt(api.ResponseBody, securitykey);
}
}
using (var writer = new StreamWriter(response))
{
await writer.WriteAsync(api.ResponseBody);
await writer.FlushAsync();
}
}
}
}
catch (Exception ex)
{
_logger.LogError($" http中間件發生錯誤: " + ex.ToString());
}
finally
{
context.Request.Body = request;
context.Response.Body = response;
}
// 響應完成時存入緩存
context.Response.OnCompleted(() =>
{
_stopwatch.Stop();
api.ElapsedTime = _stopwatch.ElapsedMilliseconds;
_logger.LogDebug($"RequestLog:{DateTime.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(0, 10000)}-{api.ElapsedTime}ms", $"{JsonConvert.SerializeObject(api)}");
return Task.CompletedTask;
});
_logger.LogInformation($"Finished handling request.{_stopwatch.ElapsedMilliseconds}ms");
}
}
2:實現中間件擴展
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseHttpContextMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<HttpContextMiddleware>();
}
}
3:在Startup使用中間件
public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpContextMiddleware(); //引入自定義的HtppContextMiddleware中間件
loggerFactory.AddLog4Net(); //引入log4net
app.UseHttpsRedirection();
app.UseMvc();
}