当前位置: 首页 > news >正文

实用指南:Python测试开发工具库:日志脱敏工具(敏感信息自动屏蔽)

目录

一、先搞懂:日志脱敏的核心需求与实现原理

1.1 核心需求拆解

1.2 实现原理

二、工具设计思路:从易用性和扩展性出发

三、代码实现:可直接复用的完整脚本

3.1 代码目录结构

3.2 配置文件:desensitize_config.json

3.3 核心脱敏模块:desensitizer.py

3.4 日志集成模块:desensitize_handler.py

3.5 演示示例:demo.py

3.6 运行效果

四、实际应用场景演示

4.1 接口测试日志脱敏

4.2 APP测试日志脱敏(Airtest集成)

五、使用注意事项

最后:工具的扩展方向


在测试开发日常工作中,日志是排查问题、跟踪流程的核心依据——接口请求参数、用户操作轨迹、数据库交互记录,都需要通过日志留存。但随之而来的问题是,这些日志里很容易夹杂敏感信息:用户的手机号、身份证号、银行卡号,甚至是数据库密码、接口Token。一旦这些日志被不当泄露,不仅可能违反数据安全相关规定,还会给用户和项目带来潜在风险。

所以,实现一套能自动识别并屏蔽敏感信息的日志脱敏工具,成了测试开发工作中的刚需。今天就带大家从零构建这个工具,涵盖从原理理解到实际落地的完整流程,最终产出可直接复用的Python 3.8.6脚本。

一、先搞懂:日志脱敏的核心需求与实现原理

1.1 核心需求拆解

在动手写代码前,先明确工具要解决的核心问题:

  • 能精准识别常见敏感信息:比如手机号(11位数字)、身份证号(18位,含X)、银行卡号(16-19位)、密码/Token(通常是长字符串或特定格式);

  • 脱敏规则可配置:不同项目的敏感信息类型可能不同,支持自定义添加/修改脱敏规则,不用改核心代码;

  • 不破坏原有日志结构:只替换敏感信息部分,保留日志的时间、级别、模块等原有字段;

  • 低侵入性:能无缝集成到Python logging模块,不用大幅修改现有日志打印逻辑。

1.2 实现原理

日志脱敏的核心逻辑很简单:“匹配-替换”两步走:

  1. 匹配:通过正则表达式,精准匹配日志文本中的敏感信息;

  2. 替换:将匹配到的敏感信息,用指定字符(比如*)进行部分或全部屏蔽,同时保留部分非敏感字符用于定位(比如手机号保留前3后4位)。

整个流程可以理解为:日志文本 → 正则匹配敏感信息 → 脱敏替换 → 输出脱敏后日志。

二、工具设计思路:从易用性和扩展性出发

结合实际工作场景,工具采用“配置化+模块化”的设计思路,拆解为3个核心模块:

  1. 配置模块:用配置文件存储脱敏规则(比如正则表达式、替换格式),支持动态修改,不用重启服务;

  2. 核心脱敏模块:封装脱敏逻辑,接收原始日志文本,应用配置的脱敏规则,返回脱敏后的文本;

  3. 日志集成模块:自定义Python logging的Handler或Filter,将脱敏逻辑嵌入日志输出流程,实现“打印即脱敏”。

这样设计的好处是:后续要新增敏感信息类型,只需修改配置文件;要适配不同的日志框架,只需调整集成模块,核心脱敏逻辑无需改动,扩展性更强。

三、代码实现:可直接复用的完整脚本

本次实现采用多文件结构,先给出整体目录,再逐一讲解各文件的功能和代码:

3.1 代码目录结构

log_desensitizer/
├── config/
│   └── desensitize_config.json  # 脱敏规则配置文件
├── core/
│   └── desensitizer.py          # 核心脱敏逻辑
├── log_handler/
│   └── desensitize_handler.py   # 日志集成Handler
└── demo.py                      # 演示示例

3.2 配置文件:desensitize_config.json

用JSON文件存储脱敏规则,每个规则包含3个核心字段:

  • rule_name:规则名称(用于标识);

  • regex:匹配敏感信息的正则表达式;

  • replace:替换格式(用group分组保留部分字符,其余用*替换)。

{"rules": [{"rule_name": "phone","regex": "1[3-9]\\d{9}","replace": "$1****$2"},{"rule_name": "id_card","regex": "(\\d{6})(\\d{8})(\\d{4})","replace": "$1********$3"},{"rule_name": "bank_card","regex": "(\\d{4})(\\d{12,15})","replace": "$1***********$2"},{"rule_name": "password","regex": "password[:=]\\s*['\"]?([^'\"]+)['\"]?","replace": "password=******"},{"rule_name": "token","regex": "token[:=]\\s*['\"]?([a-zA-Z0-9]{32,})['\"]?","replace": "token=******"}]
}

说明:

  • 手机号正则:匹配11位手机号,替换后保留前3位和后4位(比如13800138000 → 138****8000);

  • 身份证号正则:匹配18位身份证号(含X),替换后保留前6位和后4位(比如110101199001011234 → 110101********1234);

  • 密码/Token正则:匹配“password=xxx”“token=xxx”格式的字符串,直接全部替换为******。

3.3 核心脱敏模块:desensitizer.py

该模块负责加载配置文件、实现脱敏逻辑,提供一个对外的desensitize方法:

import json
import re
import os
class LogDesensitizer:def __init__(self):# 加载配置文件self.config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),"config","desensitize_config.json")self.rules = self._load_config()def _load_config(self):"""加载脱敏规则配置"""try:with open(self.config_path, "r", encoding="utf-8") as f:config = json.load(f)return config.get("rules", [])except Exception as e:print("加载脱敏配置文件失败:", str(e))return []def desensitize(self, text):"""核心脱敏方法:对输入文本应用所有脱敏规则:param text: 原始文本(日志内容):return: 脱敏后的文本"""if not text or not self.rules:return textdesensitized_text = textfor rule in self.rules:regex = rule.get("regex")replace = rule.get("replace")if not regex or not replace:continue# 应用正则替换desensitized_text = re.sub(regex, replace, desensitized_text)return desensitized_text
# 单例模式,避免重复加载配置
desensitizer = LogDesensitizer()

说明:

  • 采用单例模式创建desensitizer实例,避免每次脱敏都重新加载配置文件,提升性能;

  • _load_config方法负责读取配置文件,若读取失败则返回空列表,不影响原有日志输出;

  • desensitize方法接收原始日志文本,遍历所有脱敏规则,依次应用正则替换,返回脱敏后的文本。

3.4 日志集成模块:desensitize_handler.py

自定义logging的Handler,将脱敏逻辑嵌入日志输出流程。这里继承StreamHandler(控制台输出Handler),重写emit方法:

import logging
from core.desensitizer import desensitizer
class DesensitizeStreamHandler(logging.StreamHandler):def emit(self, record):"""重写emit方法:输出日志前先进行脱敏处理:param record: 日志记录对象"""# 获取原始日志消息msg = self.format(record)# 脱敏处理desensitized_msg = desensitizer.desensitize(msg)# 替换record的msg为脱敏后的消息record.msg = desensitized_msg# 调用父类的emit方法输出日志super().emit(record)

说明:emit方法是logging输出日志的核心方法,我们在输出前对日志消息进行脱敏处理,再调用父类方法完成输出,实现“打印即脱敏”的效果。如果需要输出到文件,可类似继承FileHandler重写emit方法。

3.5 演示示例:demo.py

编写测试代码,验证工具的脱敏效果:

import logging
from log_handler.desensitize_handler import DesensitizeStreamHandler
def setup_logger():"""配置日志器,集成脱敏Handler"""logger = logging.getLogger("test_logger")logger.setLevel(logging.DEBUG)# 移除默认Handler,避免重复输出logger.handlers.clear()# 添加脱敏Handlerhandler = DesensitizeStreamHandler()# 配置日志格式:时间-级别-模块-消息formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(module)s - %(message)s",datefmt="%Y-%m-%d %H:%M:%S")handler.setFormatter(formatter)logger.addHandler(handler)return logger
if __name__ == "__main__":logger = setup_logger()# 模拟不同场景的日志输出,包含各类敏感信息logger.debug("用户登录:手机号13800138000,密码password=12345678")logger.info("用户实名认证:身份证号110101199001011234")logger.warning("接口请求:token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...,银行卡号6222021234567890123")logger.error("数据库连接失败:url=mysql://user:password=root123@localhost:3306/test")

3.6 运行效果

执行demo.py后,控制台输出的脱敏日志如下:

2024-05-20 15:30:00 - DEBUG - demo - 用户登录:手机号138****8000,密码password=******
2024-05-20 15:30:00 - INFO - demo - 用户实名认证:身份证号110101********1234
2024-05-20 15:30:00 - WARNING - demo - 接口请求:token=******,银行卡号6222***********90123
2024-05-20 15:30:00 - ERROR - demo - 数据库连接失败:url=mysql://user:password=******@localhost:3306/test

可以看到,所有敏感信息都被成功屏蔽,同时保留了部分特征用于问题定位,符合预期效果。

四、实际应用场景演示

除了上面的基础演示,工具还能适配测试开发工作中的多种实际场景,这里举2个常见例子:

4.1 接口测试日志脱敏

在接口测试脚本中,打印请求参数和响应数据时,自动脱敏敏感信息:

import requests
from log_handler.desensitize_handler import DesensitizeStreamHandler
import logging
# 配置日志(集成脱敏Handler)
logger = logging.getLogger("api_test")
logger.setLevel(logging.INFO)
handler = DesensitizeStreamHandler()
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
def test_user_info():url = "https://api.example.com/user/info"headers = {"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}data = {"phone": "13912345678","id_card": "310101198001011234","bank_card": "6217001234567890123"}logger.info("请求用户信息接口,请求参数:%s", data)response = requests.post(url, headers=headers, json=data)logger.info("接口响应数据:%s", response.json())
if __name__ == "__main__":test_user_info()

输出日志中,手机号、身份证号、Token等敏感信息会被自动脱敏,避免泄露。

4.2 APP测试日志脱敏(Airtest集成)

在Airtest的APP自动化测试中,集成脱敏工具,屏蔽日志中的用户敏感信息:

from airtest.core.api import *
import logging
from log_handler.desensitize_handler import DesensitizeStreamHandler
# 配置Airtest日志,集成脱敏Handler
logger = logging.getLogger("airtest")
logger.setLevel(logging.INFO)
logger.handlers.clear()
handler = DesensitizeStreamHandler()
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
def test_app_login():# 连接设备connect_device("Android:///")# 启动APPstart_app("com.example.app")# 输入手机号和密码touch(Template("phone_input.png"))text("13700137000")touch(Template("password_input.png"))text("abc123456")logger.info("用户输入:手机号13700137000,密码abc123456")# 点击登录touch(Template("login_btn.png"))sleep(2)logger.info("登录操作完成")
if __name__ == "__main__":test_app_login()

Airtest运行日志中,输入的手机号和密码会被自动脱敏,保障数据安全。

五、使用注意事项

  • 正则表达式精准性:配置文件中的正则表达式需要精准匹配敏感信息,避免误脱敏。比如手机号正则要排除11位非手机号的数字串,可根据实际场景优化正则;

  • 配置文件更新:修改配置文件后,需要重启应用才能生效(若需要热更新,可在_desensitize方法中添加定时重新加载配置的逻辑);

  • 性能影响:对于日志量极大的场景,正则替换可能会影响性能。可通过限制脱敏规则数量、优化正则表达式(避免贪婪匹配)来提升性能;

  • 特殊格式敏感信息:若项目中有特殊格式的敏感信息(比如企业内部的员工编号),可在配置文件中新增对应的正则和替换规则;

  • 日志存储安全:脱敏后的日志仍需妥善存储,避免被未授权人员访问,同时保留脱敏记录,便于后续审计。

最后:工具的扩展方向

这个日志脱敏工具是基础版本,后续可根据实际需求扩展:

  • 支持更多配置格式:比如YAML配置文件,比JSON更易读;

  • 动态加载配置:通过接口或定时任务,实现配置的热更新,不用重启应用;

  • 脱敏等级配置:支持不同脱敏等级(比如部分屏蔽、全部屏蔽),根据日志用途动态切换;

  • 敏感信息统计:记录脱敏次数、敏感信息类型分布,生成统计报表,便于掌握日志安全状况。

http://www.jsqmd.com/news/379482/

相关文章:

  • 2026原创:演唱会门票在线订票系统界面(可定制)
  • ODT
  • 大模型缓存命中
  • 永无乡
  • 2026广东最新紫晶洞厂家top5推荐!广州等地优天然水晶源头供应商权威榜单,品类全货源稳,助力客商高效采购 - 品牌推荐2026
  • 信息系统仿真:信息系统基础理论_(10).仿真结果的验证与校验
  • 假期作业
  • 1950-2024年中国与各大国之间的关系数据
  • P5521 梅深不见冬
  • 2010.1-2026.1中国城市二手房房价历史数据
  • 2026广东最新结婚五金/黄金厂商首选推荐水贝黄金广州总店:广州优选,这家品牌授权店以高性价比与专业服务脱颖而出 - 品牌推荐2026
  • MySQL慢查询优化:定位、分析与优化实战
  • P9446 [ICPC 2021 WF] Prehistoric Programs
  • 别再注册Gmail了!谷歌邮箱这个隐藏功能,让你一个账号当1000个小号用(附保姆级小白教程)
  • 细胞群体动力学仿真软件:CompuCell3D_(6).模拟参数配置与优化
  • Markdown 转 Word 和 PDF:Python 简单实现指南
  • 细胞群体动力学仿真软件:CompuCell3D_(7).细胞间相互作用模型
  • P3381 【模板】最小费用最大流
  • 细胞群体动力学仿真软件:CompuCell3D_(2).细胞建模基础理论
  • P14254 分割(divide)
  • P9358 [ICPC 2022 Xian R] Bridge
  • 2026年可查实盘配资平台推荐:合规透明安全 - 资讯焦点
  • Spring Cloud 熔断降级实战:Sentinel 熔断策略与规则持久化
  • blender导出fbx没有贴图问题
  • 2026年广州家具搬运公司评测推荐榜单:告别搬家烦恼的实用指南 - 品牌推荐
  • 2026年耐介质腐蚀防护布TOP10厂商推荐榜 - 资讯焦点
  • 临沂有实力的橡胶木板材公司推荐 - 品牌推荐(官方)
  • 2026年度成熟GEO服务公司TOP7综合实力榜:AI搜索时代企业增长与选型深度指南 - 资讯焦点
  • 临沂诚信的橡胶木板材生产厂家哪家好 - 品牌推荐(官方)
  • ContextMenuManager 配置右键运行 python 脚本实现一键克隆仓库 - Higurashi