使用 ASP.NET Core HttpLoggingMiddleware 记录 http 请求/响应

        我们发布了一个应用程序,该应用程序运行在一个相当隐蔽的 WAF 后面。他们向我们保证,他们的产品不会以任何方式干扰我们的应用程序。这是错误的。他们删除了我们几乎所有的“自定义”标头。为了“证明”这一点,我构建了一个中间件,用于存储我们收到和发送的所有唯一标头。然后我创建了一个转储所有标头的端点。

我创建了一个自定义中间件,LogHeadersMiddleware

public class LogHeadersMiddleware 
{
    private readonly RequestDelegate _next;
    private readonly ILogger<LogHeadersMiddleware> _logger;
    public static readonly List<string> RequestHeaders = new List<string>();
    public static readonly List<string> ResponseHeaders = new List<string>();

    public LogHeadersMiddleware(RequestDelegate next, ILogger<LogHeadersMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        var uniqueRequestHeaders = context.Request.Headers
            .Where(x => RequestHeaders.All(r => r != x.Key))
            .Select(x => x.Key);
        RequestHeaders.AddRange(uniqueRequestHeaders);

        await _next.Invoke(context);
        var uniqueResponseHeaders = context.Response.Headers
            .Where(x => ResponseHeaders.All(r => r != x.Key))
            .Select(x => x.Key);
        ResponseHeaders.AddRange(uniqueResponseHeaders);
        
        // Log unique headers with ILogger
        ...
    }
}

然后我在中间件管道的早期就这样注册了它 

app.UseLogHeadersMiddleware();
app.Map("/show-headers", ShowHeaders);

因此,通过转到 /show-headers,您将看到我们的应用程序接收和发送的所有(唯一)标头的转储。 

新方法

微软现在已经在 ASP.NET Core 中添加了对 HTTP 日志记录的支持。
他们创建了自己的中间件,您可以像这样启用它:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // Important to have it as early as possible
    app.UseHttpLogging(); 
    ...
    ...
    ...
}

如果您不进行任何自定义,则默认记录以下内容(请求和响应):

Request path
Status code
Querystring
Headers 

示例 - 默认实现

向 /user/login
主体发出 POST 请求

{
   "username": "josef",
   "password": "MyPassword"
}

Request 

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Request:
      Protocol: HTTP/1.1
      Method: POST
      Scheme: http
      PathBase:
      Path: /user/login
      QueryString:
      Accept: */*
      Connection: keep-alive
      Host: localhost:5000
      User-Agent: PostmanRuntime/7.28.1
      Accept-Encoding: gzip, deflate, br
      Content-Type: application/json
      Content-Length: 60 

Response

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
      Response:
      StatusCode: 200
      Content-Type: application/json; charset=utf-8
      Date: [Redacted]
      Server: [Redacted]
      Transfer-Encoding: chunked 

如您所见,使用默认配置,不会记录任何敏感信息。
让我们看看如何配置中间件来记录一些敏感数据。

示例 - 记录请求/响应主体

请求正文(危险)

这将记录请求标头和正文

services.AddHttpLogging(options =>
{
    options.LoggingFields = HttpLoggingFields.RequestPropertiesAndHeaders |
                            HttpLoggingFields.RequestBody;
});

Body体

{
    "username": "josef",
    "password": "MyPassword"
}

Request 

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Request:
      Protocol: HTTP/1.1
      Method: POST
      Scheme: http
      PathBase:
      Path: /user/login
      QueryString:
      Accept: */*
      Connection: keep-alive
      Host: localhost:5000
      User-Agent: PostmanRuntime/7.28.1
      Accept-Encoding: gzip, deflate, br
      Content-Type: application/json
      Content-Length: 60

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
      RequestBody: {
          "username": "josef",
          "password": "MyPassword"
      }

响应主体(危险)

这将记录响应标头和正文

services.AddHttpLogging(options =>
{
    options.LoggingFields = HttpLoggingFields.ResponsePropertiesAndHeaders |
                            HttpLoggingFields.ResponseBody;
});

Body

{
    "username": "josef",
    "password": "MyPassword"
}

Response

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Response:
      StatusCode: 200
      Content-Type: application/json; charset=utf-8

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
      ResponseBody: {"token":"very secret token"}

        如您所见,我们现在正在记录请求和响应主体。这在开发/调试期间可能非常有用,但您很可能永远不想在生产中这样做。通过盲目地记录请求/响应标头/主体,您可以(很可能)记录敏感数据。如果您觉得有必要记录标头和主体,请确保使用选择加入策略,如下所示:

services.AddHttpLogging(options =>
{
    options.LoggingFields = HttpLoggingFields.RequestPropertiesAndHeaders |
                            HttpLoggingFields.ResponsePropertiesAndHeaders;
    options.ResponseHeaders.Add("Non-Sensitive");
});

调用以下操作时...

[HttpGet("api/weather")]
public IActionResult Index()
{
    Response.Headers.Add("Sensitive", "034D4CD7-2FEB-4B19-86A3-CFCD5DB291AA");
    Response.Headers.Add("Non-Sensitive", "Hello");
    return new OkObjectResult(new
    {
        data = "Hello World"
    });

...仅会记录非敏感标头 

Request

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
Response:
StatusCode: 200
Content-Type: application/json; charset=utf-8
Date: [Redacted]
Server: [Redacted]
Transfer-Encoding: chunked
Sensitive: [Redacted]
Non-Sensitive: Hello

表现

考虑记录请求/响应主体时应用程序的性能会受到怎样的影响也很重要
。GET

没有 HttpLogging

❯ .\bombardier.exe -c 125 -n 100000 http://localhost:5000/api/weather
Bombarding http://localhost:5000/api/weather with 100000 request(s) using 125 connection(s)
 100000 / 100000 [==========================================] 100.00% 2287/s 43s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec      2292.70     326.38    7095.61
  Latency       54.52ms     2.29ms   109.00ms
  HTTP codes:
    1xx - 0, 2xx - 100000, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:   727.39KB/s

HttpLogging 的默认设置

❯ .\bombardier.exe -c 125 -n 100000 http://localhost:5000/api/weather
Bombarding http://localhost:5000/api/weather with 100000 request(s) using 125 connection(s)
 100000 / 100000 [==========================================] 100.00% 1492/s 1m6s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec      1496.73     287.61    4500.00
  Latency       83.52ms    15.73ms      0.86s
  HTTP codes:
    1xx - 0, 2xx - 100000, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:   474.86KB/s

已启用请求/响应主体日志记录

❯ .\bombardier.exe -c 125 -n 100000 http://localhost:5000/api/weather
Bombarding http://localhost:5000/api/weather with 100000 request(s) using 125 connection(s)
 100000 / 100000 [==========================================] 100.00% 1466/s 1m8s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec      1471.50     285.97    5090.86
  Latency       84.96ms    17.64ms      0.87s
  HTTP codes:
    1xx - 0, 2xx - 100000, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:   466.79KB/s

当打开HttpLogging时,吞吐量从 ~2300 req/s 变为 ~1500 req/
s.POST

没有 HttpLogging

❯ .\bombardier.exe -m POST http://localhost:5000/user/login -c 125 -n 100000 --duration 1s -l -H "Content-Type: application/json" -f "login.json"
Bombarding http://localhost:5000/user/login with 100000 request(s) using 125 connection(s)
 100000 / 100000 [==========================================] 100.00% 2112/s 47s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec      2118.76     444.32    6498.38
  Latency       59.03ms    14.41ms   576.00ms
  Latency Distribution
     50%    57.00ms
     75%    59.96ms
     90%    70.00ms
     95%    75.00ms
     99%    90.81ms
  HTTP codes:
    1xx - 0, 2xx - 100000, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:   771.02KB/s

HttpLogging 的默认设置

❯ .\bombardier.exe -m POST http://localhost:5000/user/login -c 125 -n 100000 --duration 1s -l -H "Content-Type: application/json" -f "login.json"
Bombarding http://localhost:5000/user/login with 100000 request(s) using 125 connection(s)
 100000 / 100000 [==========================================] 100.00% 1388/s 1m12s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec      1392.11     328.62    8995.50
  Latency       89.92ms    19.01ms      1.09s
  Latency Distribution
     50%    88.00ms
     75%    91.00ms
     90%    97.00ms
     95%   111.00ms
     99%   125.00ms
  HTTP codes:
    1xx - 0, 2xx - 100000, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:   506.18KB/s

已启用请求/响应主体日志记录

❯ .\bombardier.exe -m POST http://localhost:5000/user/login -c 125 -n 100000 --duration 1s -l -H "Content-Type: application/json" -f "login.json"
Bombarding http://localhost:5000/user/login with 100000 request(s) using 125 connection(s)
 100000 / 100000 [==========================================] 100.00% 1281/s 1m18s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec      1284.89     311.66    4550.25
  Latency       97.31ms    21.58ms      1.22s
  Latency Distribution
     50%    95.00ms
     75%    99.00ms
     90%   108.00ms
     95%   119.00ms
     99%   150.00ms
  HTTP codes:
    1xx - 0, 2xx - 100000, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:   467.73KB/s

我们可以看到,记录更多内容会对性能造成影响。记录请求/响应主体时,我们每秒会额外损失约 100 个请求。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/933655.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

后端工程搭建

后端工程通过maven聚合工程的形式来搭建 1.1创建spzx-parent工程(父工程) 存放公共依赖 锁定公共依赖版本 1.2创建spzx-common工程(公共模块) 存放一些工具类/公共服务 1.3创建spzx-model工程(数据模型) 存放实体类 1.4创建spzx-menager工程(后台管理系统) 后台管理系统服务模…

Flink Python作业快速入门

Flink Python快速入门_实时计算 Flink版(Flink)-阿里云帮助中心 import argparse # 用于处理命令行参数和选项&#xff0c;使程序能够接收用户通过命令行传递的参数 import logging import sysfrom pyflink.common import WatermarkStrategy, Encoder, Types from pyflink.data…

数字图像处理(15):图像平移

&#xff08;1&#xff09;图像平移的基本原理&#xff1a;计算每个像素点的移动向量&#xff0c;并将这些像素按照指定的方向和距离进行移动。 &#xff08;2&#xff09;平移向量包括水平和垂直分量&#xff0c;可以表示为&#xff08;dx&#xff0c;dy&#xff09;&#xff…

JAVA秋招面试题精选-第一天总结

目录 分栏简介&#xff1a; 问题一&#xff1a;订单表每天新增500W条数据&#xff0c;分库分表应该怎么设计&#xff1f; 问题难度以及频率&#xff1a; 问题导向&#xff1a; 满分答案&#xff1a; 举一反三&#xff1a; 问题总结&#xff1a; 问题二&#xff1a;解释…

Rnnoise和SpeexDsp两种降噪方式有什么区别?

在蒙以CourseMaker 7.0软件中&#xff0c;增加了两种降噪模式&#xff0c;一种是Rnnoise&#xff0c;一种是SpeexDsp&#xff0c;这两种降噪模式有什么区别呢&#xff1f; Rnnoise 基于神经网络。当噪声与 rnnoise 的模型训练的噪声匹配时&#xff0c;它的效果非常好。比如说&…

博物馆导览系统方案(一)背景需求分析与核心技术实现

维小帮提供多个场所的室内外导航导览方案&#xff0c;如需获取博物馆导览系统解决方案可前往文章最下方获取&#xff0c;如有项目合作及技术交流欢迎私信我们哦~撒花&#xff01; 一、博物馆导览系统的背景与市场需求 在数字化转型的浪潮中&#xff0c;博物馆作为文化传承和知…

福昕PDF低代码平台

福昕PDF低代码平台简介 福昕PDF 低代码平台是一款创新的工具&#xff0c;旨在简化PDF处理和管理的流程。通过这个平台&#xff0c;用户可以通过简单的拖拽界面上的按钮&#xff0c;轻松完成对Cloud API的调用工作流&#xff0c;而无需编写复杂的代码。这使得即使没有编程经验的…

Linux —— 管理文件

一、Linux的目录结构及用途 /bin&#xff1a;存放最常用的命令&#xff0c;如ls、cat等&#xff0c;所有用户都可以执行的命令。/boot&#xff1a;包含启动Linux系统所需的核心文件&#xff0c;如内核文件和引导加载程序。/dev&#xff1a;设备文件目录&#xff0c;包含系统中的…

NanoLog起步笔记-7-log解压过程初探

nonolog起步笔记-6-log解压过程初探 再看解压过程建立调试工程修改makefile添加新的launch项 注&#xff1a;重新学习nanolog的README.mdPost-Execution Log Decompressor 下面我们尝试了解&#xff0c;解压的过程&#xff0c;是如何得到文件头部的meta信息的。 再看解压过程 …

处理配置System Viewer缺少SFR文件

按照网上的教程&#xff0c;其他的都配好 这里给几个参考 嵌入式开发--Keil MDK仿真时System Viewer不显示寄存器选项_keil system viewer不显示外设寄存器-CSDN博客 keil无法查看外设寄存器&#xff08;生成SFR文件&#xff09;_keil sfr文件-CSDN博客 keil5软件仿真 Logic…

网络安全中大数据和人工智能应用实践

传统的网络安全防护手段主要是通过单点的网络安全设备&#xff0c;随着网络攻击的方式和手段不断的变化&#xff0c;大数据和人工智能技术也在最近十年飞速地发展&#xff0c;网络安全防护也逐渐开始拥抱大数据和人工智能。传统的安全设备和防护手段容易形成数据孤岛&#xff0…

create-react-app react19 搭建项目报错

报错截图 此时运行会报错&#xff1a; 解决方法&#xff1a; 1.根据提示安装依赖法 执行npm i web-vitals然后重新允许 2.删除文件法 在index.js中删除对报错文件的引入&#xff0c;删除报错文件

excel如何让单元格选中时显示提示信息?

现象&#xff1a; 当鼠标放在单元格上&#xff0c;会出现提示信息&#xff1a; 先选中单元格选择上方的【数据】-【数据验证】图标选择【输入信息】勾上【选定单元格时显示输入信息】输入【标题】&#xff0c;如&#xff1a;最上方图中的&#xff1a;姓名&#xff1a;输入【输…

PyCharm+Selenium+Pytest配置小记

1、下载ChromeDriver&#xff1a; Chrome130以后的Driver下载&#xff1a; Chrome for Testing availabilityhttps://googlechromelabs.github.io/chrome-for-testing/ &#xff08;1&#xff09;查看自己Crome浏览器的版本&#xff1a;设置-->关于 Chrome&#xff1b; &…

用最小的代价解决mybatis-plus关于批量保存的性能问题

1.问题说明 问题背景说明&#xff0c;在使用达梦数据库时&#xff0c;mybatis-plus的serviceImpl.saveBatch()方法或者updateBatchById()方法的时候&#xff0c;随着数据量、属性字段的增加&#xff0c;效率越发明显的慢。 serviceImpl.saveBatch(); serviceImpl.updateBatch…

电子商务人工智能指南 4/6 - 内容理解

介绍 81% 的零售业高管表示&#xff0c; AI 至少在其组织中发挥了中等至完全的作用。然而&#xff0c;78% 的受访零售业高管表示&#xff0c;很难跟上不断发展的 AI 格局。 近年来&#xff0c;电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

Helm安装Mysql8主从复制集群

目录 一、Helm安装 二、安装mysql 1、拉取镜像 2、修改配置文件 3、创建mysql-secret 4、安装 一、Helm安装 这里不再赘叙&#xff0c;具体安装请参考官网 Helm | 快速入门指南 二、安装mysql 1、拉取镜像 #添加仓库 helm repo add bitnami https://charts.bitnami.c…

Java并发编程学习之从资本家的角度看多线程和并发性(一)

目录 前言前置知识一、单线程时代二、为什么要有多线程&#xff0c;多线程的优点&#xff1f;三、使用多线程会遇到什么问题&#xff1f;四、多线程和并发编程的关系总结 前言 这篇文章是打开Java多线程和并发编程的大门的开始&#xff0c;如标题《从老板的角度看多线程和并发…

【爬虫】selenium打开浏览器以及页面

本篇探讨如何使用 selenium 打开浏览器 selenium 基础与网页打开 selenium 是一个广泛应用于自动化测试和网页抓取的工具&#xff0c;它能够模拟用户在浏览器中的各种操作。首先&#xff0c;我们需要根据指定的浏览器类型&#xff08;这里以 Chrome 为例&#xff09;打开网页…

【算法练习】162. 寻找峰值

题目链接&#xff1a;162. 寻找峰值 看思路图&#xff1a; class Solution { public:int findPeakElement(vector<int>& nums) {int left 0,right nums.size()-1;while(left<right){int mid left (right-left)/2;if(nums[mid]>nums[mid1]){right mid;}els…