Python 日志记录实战:结构化日志与敏感信息脱敏

举报
yd_70403235 发表于 2026/10/31 21:13:05 2026/10/31
【摘要】 用 Python 标准库 logging 输出结构化 JSON 日志,并对密码、Token 等敏感字段做脱敏,避免日志本身变成新的安全风险。

Python 日志记录实战:结构化日志与敏感信息脱敏

很多项目一开始只用 print 排查问题,等到线上出问题时才发现:日志没有级别、没有统一格式、还可能把密码和 Token 直接写进文件。本文用 Python 标准库 logging 做一个最小可用的方案:输出结构化 JSON 日志,同时对敏感字段脱敏。

1. 为什么不要直接打印字典

直接把请求参数、用户信息打印出来,很容易顺带打印出密码、Token、AK/SK。日志一旦落盘、上传或被其他人看到,就很难收回。所以第一条规则是:日志字段先过一层脱敏,再输出。

2. 一个可复用的脱敏函数

对字典和列表做递归处理,键名包含 password、token、ak、secret 等敏感词时替换为 ***,其他字段原样保留:

SENSITIVE = ("password", "token", "ak", "secret")

def redact(obj):
    if isinstance(obj, dict):
        return {
            k: ("***" if any(s in k.lower() for s in SENSITIVE) else redact(v))
            for k, v in obj.items()
        }
    if isinstance(obj, list):
        return [redact(v) for v in obj]
    return obj

注意,这里的匹配是按“包含”来做的,比精确匹配更稳妥,但也可能误伤,例如把 tokenizer 当成敏感字段。实际项目里可以改成白名单加黑名单结合:先明确哪些字段允许记录,再对剩余字段做脱敏。

3. 输出 JSON,而不是拼接字符串

拼接字符串的日志很难被搜索和分析。把级别、消息、业务字段统一成 JSON,之后用 jq、日志平台按字段过滤都会方便很多:

import json, logging

class JsonFormatter(logging.Formatter):
    def format(self, record):
        payload = {
            "level": record.levelname,
            "msg": record.getMessage(),
            "name": record.name,
        }
        if record.args and isinstance(record.args, dict):
            payload.update(redact(record.args))
        return json.dumps(payload, ensure_ascii=False)

使用时把业务字段作为字典传进去,而不是拼进消息字符串里,这样字段结构始终稳定。

4. 本地验证

下面这段代码在本地直接运行过,输出证明密码和 Token 已被替换,级别和字段也都正常:

import io

stream = io.StringIO()
handler = logging.StreamHandler(stream)
handler.setFormatter(JsonFormatter())
log = logging.getLogger("demo")
log.handlers = [handler]
log.setLevel(logging.INFO)
log.propagate = False

log.info("user login", {"user": "demo", "password": "hunter2", "token": "abc123"})
print(stream.getvalue())

输出示例:

{"level": "INFO", "msg": "user login", "name": "demo", "user": "demo", "password": "***", "token": "***"}

5. 几个容易踩的坑

  • 不要在日志里记录完整请求体:先明确字段清单,只记排查需要的部分。
  • 异常日志要带上下文,不要只记一句话:至少保留操作、关键标识和错误类型,敏感字段同样要脱敏。
  • 级别要分开用:INFO 记正常关键节点,WARNING 记可恢复的异常,ERROR 记需要人工介入的失败,不要全部用 INFO。
  • 脱敏要在输出前做,不要事后去文件里替换:事后替换容易漏掉滚动文件、备份文件和已经上传的副本。

小结

结构化日志解决的是“能不能快速查到问题”,脱敏解决的是“日志本身会不会变成新的风险”。两者都不需要引入第三方库,Python 标准库就能先把基本盘做好,再根据项目规模决定是否接入统一日志平台。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。