GitHub demo https://github.com/zhanglilong23/Asp.NetCore.Demo

本项目使用中间件拦截请求数据,并对请求数据解密。 访问接口成功后拦截返回数据,然后将返回数据加密后返回。

其中log4net部分不再赘述(demo中有介绍)

将Post方法中Body中的数据进行AES解密

将返回数据进行AES加密

1. 自定义中间件,并默认实现Invoke方法. 附带使用日志记录错误和访问时间等。

  1. public class HttpContextMiddleware
  2. {
  3. private readonly RequestDelegate _next;
  4. private readonly ILogger _logger;
  5. /// <summary>
  6. /// 计时器
  7. /// </summary>
  8. private Stopwatch _stopwatch;
  9. //加密解密key
  10. private readonly string securitykey = "0123456789abcdef";
  11. /// <summary>
  12. /// 构造 Http 请求中间件
  13. /// </summary>
  14. /// <param name="next"></param>
  15. /// <param name="loggerFactory"></param>
  16. /// <param name="cacheService"></param>
  17. public HttpContextMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
  18. {
  19. _next = next;
  20. _logger = loggerFactory.CreateLogger<HttpContextMiddleware>();
  21. }
  22. /// <summary>
  23. /// 1:将Post方法中Body中的数据进行AES解密
  24. /// 2:将返回数据进行AES加密
  25. /// </summary>
  26. /// <param name="context"></param>
  27. /// <returns></returns>
  28. public async Task Invoke(HttpContext context)
  29. {
  30. context.Request.EnableBuffering();
  31. _stopwatch = new Stopwatch();
  32. _stopwatch.Start();
  33. _logger.LogInformation($"Handling request: " + context.Request.Path);
  34. var api = new ApiRequestInputViewModel
  35. {
  36. HttpType = context.Request.Method,
  37. Query = context.Request.QueryString.Value,
  38. RequestUrl = context.Request.Path,
  39. RequestName = "",
  40. RequestIP = context.Request.Host.Value
  41. };
  42. var request = context.Request.Body;
  43. var response = context.Response.Body;
  44. try
  45. {
  46. using (var newRequest = new MemoryStream())
  47. {
  48. //替换request流
  49. context.Request.Body = newRequest;
  50. using (var newResponse = new MemoryStream())
  51. {
  52. //替换response流
  53. context.Response.Body = newResponse;
  54. using (var reader = new StreamReader(request))
  55. {
  56. //读取原始请求流的内容
  57. api.Body = await reader.ReadToEndAsync();
  58. if (string.IsNullOrEmpty(api.Body))
  59. await _next.Invoke(context);
  60. //示例加密字符串,使用 AES-ECB-PKCS7 方式加密,密钥为:0123456789abcdef
  61. // 加密参数:{"value":"哈哈哈"}
  62. // 加密后数据: oedwSKGyfLX8ADtx2Z8k1Q7+pIoAkdqllaOngP4TvQ4=
  63. api.Body = SecurityHelper.AESDecrypt(api.Body, securitykey);
  64. }
  65. using (var writer = new StreamWriter(newRequest))
  66. {
  67. await writer.WriteAsync(api.Body);
  68. await writer.FlushAsync();
  69. newRequest.Position = 0;
  70. context.Request.Body = newRequest;
  71. await _next(context);
  72. }
  73. using (var reader = new StreamReader(newResponse))
  74. {
  75. newResponse.Position = 0;
  76. api.ResponseBody = await reader.ReadToEndAsync();
  77. if (!string.IsNullOrWhiteSpace(api.ResponseBody))
  78. {
  79. api.ResponseBody = SecurityHelper.AESEncrypt(api.ResponseBody, securitykey);
  80. }
  81. }
  82. using (var writer = new StreamWriter(response))
  83. {
  84. await writer.WriteAsync(api.ResponseBody);
  85. await writer.FlushAsync();
  86. }
  87. }
  88. }
  89. }
  90. catch (Exception ex)
  91. {
  92. _logger.LogError($" http中间件发生错误: " + ex.ToString());
  93. }
  94. finally
  95. {
  96. context.Request.Body = request;
  97. context.Response.Body = response;
  98. }
  99. // 响应完成时存入缓存
  100. context.Response.OnCompleted(() =>
  101. {
  102. _stopwatch.Stop();
  103. api.ElapsedTime = _stopwatch.ElapsedMilliseconds;
  104. _logger.LogDebug($"RequestLog:{DateTime.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(0, 10000)}-{api.ElapsedTime}ms", $"{JsonConvert.SerializeObject(api)}");
  105. return Task.CompletedTask;
  106. });
  107. _logger.LogInformation($"Finished handling request.{_stopwatch.ElapsedMilliseconds}ms");
  108. }
  109. }

2. 实现中间件扩展

  1. public static class MiddlewareExtensions
  2. {
  3. public static IApplicationBuilder UseHttpContextMiddleware(this IApplicationBuilder builder)
  4. {
  5. return builder.UseMiddleware<HttpContextMiddleware>();
  6. }
  7. }

3. 在Startup使用中间件

  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerFactory)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. }
  7. else
  8. {
  9. // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
  10. app.UseHsts();
  11. }
  12. app.UseHttpContextMiddleware(); //引入自定义的HtppContextMiddleware中间件
  13. loggerFactory.AddLog4Net(); //引入log4net
  14. app.UseHttpsRedirection();
  15. app.UseMvc();
  16. }