反序列化调试 Proto 表示
从版本 30.x 开始,Protobuf `DebugString` API(`Message::DebugString`、`Message::ShortDebugString`、`Message::Utf8DebugString`)、额外的 Protobuf API(`proto2::ShortFormat`、`proto2::Utf8Format`)、Abseil 字符串函数(如 `absl::StrCat`、`absl::StrFormat`、`absl::StrAppend` 和 `absl::Substitute`)以及 Abseil 日志记录 API 将开始自动将 proto 参数转换为新的调试格式。请参阅此处的相关公告。
与 Protobuf DebugString 输出格式不同,新的调试格式会自动删除敏感字段,将其值替换为字符串“[REDACTED]”(不含引号)。此外,为了确保无论底层 proto 是否包含 SPII 字段,这种新输出格式都无法被 Protobuf TextFormat 解析器反序列化,我们添加了一组随机生成的指向本文的链接和随机长度的空格序列。新的调试格式如下所示:
goo.gle/debugstr
spii_field: [REDACTED]
normal_field: "value"
请注意,新的调试格式与 DebugString 格式的输出格式仅在两个方面不同:
- URL 前缀
- SPII 字段的值被替换为“[REDACTED]”(不含引号)
新的调试格式绝不会删除任何字段名称;只有当字段被视为敏感时,它才会将其值替换为“[REDACTED]”。如果您在输出中没有看到某些字段,那是因为这些字段在 proto 中没有设置。
提示:如果您只看到 URL 而没有其他内容,说明您的 proto 是空的!
为什么这里有这个 URL?
我们希望确保没有人反序列化旨在供人类调试系统的 protobuf 消息的人类可读表示。历史上,`.DebugString()` 和 `TextFormat` 是可以互换的,现有系统使用 DebugString 来传输和存储数据。
我们希望确保敏感数据不会意外地出现在日志中。因此,我们会在将 protobuf 消息转换为字符串(“[REDACTED]”)之前,透明地删除其中一些敏感字段的值。这降低了意外记录敏感数据的安全和隐私风险,但如果其他系统反序列化您的消息,则存在数据丢失的风险。为了解决此风险,我们有意将机器可读的 TextFormat 与用于日志消息的人类可读调试格式分开。
为什么我的网页里有链接?为什么我的代码会产生这种新的“调试表示”?
这是有意为之,目的是使您的 protos 的“调试表示”(例如由日志记录产生)与 TextFormat 不兼容。我们希望阻止任何人依赖调试机制在程序之间传输数据。历史上,调试格式(由 DebugString API 生成)和 TextFormat 被不正确地互换使用。我们希望这种有意为之的努力能够阻止这种情况的发生。
我们有意选择链接而非不那么明显的格式更改,以便有机会提供上下文。这在用户界面中可能会很醒目,例如当您在网页表格中显示状态信息时。您可以改用 `TextFormat::PrintToString`,它不会删除任何信息并保留格式。但是,请谨慎使用此 API – 它没有内置保护。作为经验法则,如果您将数据写入调试日志或生成状态消息,您应该继续使用带链接的调试格式。即使您目前不处理敏感数据,请记住系统可能会发生变化,并且代码会被重复使用。
我尝试将此消息转换为 TextFormat,但我注意到每次进程重启时格式都会改变。
这是有意为之。不要尝试解析此调试格式的输出。我们保留随时更改语法的权利,恕不另行通知。调试格式语法因进程而异,以防止意外依赖。如果调试格式的语法更改会破坏您的系统,那么很可能您应该使用 TextFormat API,而不是使用 proto 的调试表示。
常见问题解答
我可以到处都使用 TextFormat 吗?
不要使用 TextFormat 生成日志消息。这将绕过所有内置保护,并且您可能会意外记录敏感信息。即使您的系统目前不处理任何敏感数据,未来也可能会发生变化。
通过根据需要使用调试表示或 TextFormat 来区分日志和旨在由其他系统进一步处理的信息。
我想编写既需要人类可读又需要机器可读的配置文件
对于此用例,您可以明确使用 TextFormat。您有责任确保您的配置文件不包含任何 PII。
我正在编写单元测试,并想在测试断言中比较 Debugstring
如果您想比较 protobuf 的值,请使用 `MessageDifferencer`,如下所示:
using google::protobuf::util::MessageDifferencer;
...
MessageDifferencer diff;
...
diff.Compare(foo, bar);
除了忽略格式和字段顺序的差异外,您还将获得更好的错误消息。