asp.net core 使用中間件攔截請求和返回數據,並對數據進行加密解密。

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();
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章