开发者工具 · UUID 生成器
是什么使 UUID 字符串格式良好,以及检查器无法知道的内容
· 工作原理
uuid 密码学 浏览器 API
大写、大括号、urn:前缀和缺失的连字符都会出现在实际输入中。这篇文章定义了规范形式,展示了宽松的验证者应该接受的内容,并将格式良好与存在分开。
应该是 404 的 400 — 草率的 UUID 验证会产生令人困惑的 API 错误
API 端点从客户端接收标识符:{12345678-90AB-CDEF-1234-567890ABCDEF}。验证代码检查它是否匹配 /[0-9a-f]{32}/ 并将其视为无效而拒绝。客户端收到 400 错误请求,其含义是 404 Not Found。该标识符格式良好 - 它是大括号格式的有效 UUID - 但验证器过于严格。相反,接受任何 32 字符十六进制字符串(不带破折号)的端点将接受 123456789012345678901234567890123456,将其解析为有效,并错过拼写错误。 RFC 9562 定义了规范的文本表示形式,但现实世界的输入以五种不同的格式到达,并且仅接受规范形式的验证器将拒绝 1 到 5 的善意输入。
规范文本形式 — 8-4-4-4-12 中的 32 小写十六进制数字,恰好是 36 个字符,如标准为输出指定的那样
规范的文本形式是 32 小写十六进制数字,分为五组,用连字符分隔:8-4-4-4-12。表示为 550e8400-e29b-41d4-a716-446655440000。该标准要求输出小写;在输入时,建议不区分大小写匹配。这种形式是明确的,在每个平台上都以相同的方式解析为字节,并且是每个 UUID 库默认输出的形式。如果您要从 CSPRNG 生成新的 UUID,则规范形式就是您应该生成的内容以及 ToolAcre 生成的内容。现实世界的输入会以可预测的方式出现偏差。大写标识符 (550E8400-E29B-41D4-A716-446655440000) 在默认为大写的系统中很常见;它们代表相同的字节,在标准化为小写后应被接受。
您将在野外遇到的变体 — 大写十六进制、{braces}、urn:uuid: 前缀和 32 字符无连字符形式,以及标准规定接受的变体
大括号形式 ({550e8400-e29b-41d4-a716-446655440000}) 是 Python 的 uuid 模块和 Microsoft 系统的标准输出;去掉大括号给出了有效的规范形式。 URN 前缀 (urn:uuid:550e8400-e29b-41d4-a716-446655440000) 由 RFC 8141 定义,用于统一资源名称;删除方案和剥离标识符前缀留下规范形式。无连字符形式 (550e8400e29b41d4a716446655440000) 是没有结构的 32 十六进制数字;它是有效字节,但丢失了 8-4-4-4-12 分组,使版本和变体可读。这些变体都映射到相同的 128 位值。 RFC 9562 部分 3 声明在输入时,应该接受大写变体。它并不禁止其他变体;它表示在输出时,必须使用规范的小写形式。
版本和变体健全性 — 是否拒绝第三组以 0 开头或第四组以 f 开头的 UUID
格式良好的验证器应该: 接受小写或大写的规范 8-4-4-4-12 形式;通过剥离它们并验证核心形式来接受 braced 和 urn: 变体;接受无连字符的 32 位十六进制字符串并将其格式化为规范以进行比较;拒绝十六进制数字或非十六进制字符数量错误的字符串。最常见的错误是拒绝大写或大括号输入,因为验证器是手写的,仅匹配规范形式。对版本和变体进行健全性检查可以发现拼写错误。如果第三组以0或9开头,则UUID无效或被保留;如果第四组以 e 或 f 开头,则变体不是 RFC 9562。
工作示例 — 六个候选字符串经过严格检查和宽松检查,并附有每个通过或失败的原因
宽松的验证器接受这些值;严格的验证者可以拒绝它们。 ToolAcre 格式正确的检查执行严格的验证:它确认规范的 36 字符形式,并在正确的位置使用破折号,验证每个位置的十六进制数字,并检查版本和变体位是否在范围内。它不会检查 UUID 是否存在于您的数据库中,或者它是否是从加密安全源生成的;这些是由您的应用程序逻辑完成的单独检查。格式正确的并不等于真实的。根据其形状正确解析的 UUID 字符串可能无法识别数据库中的任何行。
格式良好并不真实 - 为什么语法上完美的 UUID 可能不存在于您的数据中,以及为什么检查器永远不应该成为您的授权层
格式完美的 UUID 可能被错误地猜测或复制粘贴。格式验证是第一道关卡;存在检查和授权检查是第二和第三。对数据库中的每个格式无效的输入进行查找是一种浪费;在数据库查询之前拒绝格式无效的输入可以节省时间。 ToolAcre 生成器输出标准 36 字符 UUID;如果您正在构建自己的验证器,请接受花括号和 urn: 变体以匹配现实世界的输入,并在询问数据库之前拒绝不符合基本形状规则的字符串。实现严格的验证器需要正则表达式和边缘情况处理。规范形式很简单:/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i(不区分大小写)。大括号形式添加大括号:/^\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}$/i. urn: 变体添加方案:/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.
这不包括什么 - 标准化存储 ID 和选择列类型,这是单独的决定
处理所有变体的单个正则表达式可读性较差,但也是可能的。大多数验证器首先进行规范化:去掉大括号和 urn: 前缀,转换为小写,然后匹配规范模式。可以在模式匹配后通过检查位置 14 和位置 19 来检查版本和变体位,如 403 文章中所述。优雅地处理无效输入是验证设计的一部分。当客户端提交格式错误的 UUID 时,请勿在错误消息中公开正则表达式模式或内部验证规则。返回明确的错误:“无效的 UUID 格式。应为 8-4-4-4-12 格式,例如 550e8400-e29b-41d4-a716-446655440000。” 不要尝试纠正输入;要求客户重新提交。
要点:尽早验证形状,单独查找是否存在 — ToolAcre 检查会在您接触数据库之前确认浏览器中的形状
某些系统会记录无效输入以进行安全审核(检测尝试注入或格式混淆攻击)。 ToolAcre 验证器会拒绝非规范表单并给出明确的错误消息,并且不会尝试自动更正。为什么规范形式对于互操作性很重要:如果一个系统将 UUID 存储为无连字符的十六进制,而另一个系统将它们存储为规范 8-4-4-4-12,则比较它们是否相等需要标准化。大写与小写需要进行不区分大小写的比较。支撑与裸露需要剥离。这些变化使得批量操作(导入、迁移、比较)变得更加困难。输出规范形式的标准工具可以减少摩擦。 ToolAcre 生成器始终输出 36 字符小写规范形式;当您从其他系统导入 UUID 时,请在 ETL 过程中将它们标准化为这种形式,以确保一致性。