作为后端工程师,我们经常负责构建可以扩展和处理大量资源、用户和实体的系统,每个资源、用户和实体都需要唯一的标识。在许多情况下,使用顺序 ID(例如 1、2、3)似乎是一个简单的解决方案,但随着应用程序在分布式系统中增长和扩展,这很快就会成为问题。这就是 UUID(通用唯一标识符)发挥作用的地方。
在这篇博文中,我们将探讨:
UUID(通用唯一标识符)是一个 128 位数字,用于唯一标识计算机系统中的信息。它被设计为全球唯一,这意味着在不同系统中独立生成的UUID不会发生冲突。
UUID 看起来像这样:
66e69275-c6bc-800c-90a6-2f41cb991502
由32个十六进制数字组成,分五组显示,用连字符分隔,形式为8-4-4-4-12。
分布式系统中的数据库密钥:在不同数据库或微服务需要生成唯一ID而不互相通信的系统中,UUID确保唯一性。例如,在分布式电子商务平台中,每个服务可能独立生成订单或交易 ID,UUID 将避免任何冲突。
会话 ID:UUID 通常用于标识 Web 应用程序中的用户会话。当您需要维护会话信息而不泄露敏感或可预测数据时,它们特别有用。
文件或资源标识符:当您需要跨不同平台或数据库跟踪文件、文档或任何资源时,可以为每个资源分配一个 UUID,以便于查找,而无需担心重复。
API 和外部引用:在 API 中暴露连续或容易猜测的 ID(例如 user/1、user/2)可能会导致隐私漏洞。通过使用 UUID(例如 user/66e69275-c6bc-800c-90a6-2f41cb991502),您可以减少用户猜测和访问不属于他们的资源的可能性。
Python 的 uuid 库使生成和管理 UUID 变得简单。方法如下:
import uuid # Generate a UUID generated_uuid = uuid.uuid4() print(f"Generated UUID: {generated_uuid}")
uuid4() 函数根据随机或伪随机数生成随机 UUID,这是 Web 开发中最常见的变体。
当使用像 PostgreSQL 这样的数据库时,通常使用 UUID 作为主键。以下是如何使用 SQLAlchemy 在 Python 中进行设置:
from sqlalchemy import Column, String from sqlalchemy.dialects.postgresql import UUID import uuid from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) username = Column(String, nullable=False) # This will generate a UUID primary key for each new user.
在此示例中,我们将 id 字段定义为 UUID,确保每个用户都有一个唯一的标识符,即使跨分布式数据库,也不会与其他记录冲突。
忽略 UUID 而选择顺序或自动递增 ID 可能会带来多种风险:
安全漏洞:序列 ID 是可预测的,使攻击者可以轻松枚举记录并发现敏感数据。例如,如果用户 ID 是连续的,攻击者可能会尝试猜测其他用户 ID 并访问未经授权的帐户。
数据冲突:在分布式系统中,依赖自增整数可能会导致ID冲突,特别是当多个服务或数据库在没有中央协调的情况下生成ID时。
数据迁移和合并问题:当组合数据库或跨系统迁移数据时,具有非唯一的顺序ID可能会导致冲突。 UUID 通过保证唯一性来避免这些问题。
将 UUID 存储为字符串:一个常见的错误是将 UUID 存储为字符串,这会浪费空间并降低查询速度,尤其是在大型数据库中。大多数现代数据库(例如 PostgreSQL)都具有可有效存储 UUID 的本机 UUID 类型。
错误的:
CREATE TABLE users ( id VARCHAR(36) PRIMARY KEY );
正确的:
CREATE TABLE users ( id UUID PRIMARY KEY );
未使用正确的 UUID 版本:UUID 有多个版本(例如,uuid1()、uuid3()、uuid4()、uuid5()),每个版本都适合特定用途案例。 uuid4() 基于随机数,最常用于在 Web 应用程序中生成唯一 ID。请注意您正在使用哪个版本以及它是否适合您的需求。
忽略碰撞可能性:虽然 UUID 被设计为唯一的,但发生碰撞的可能性非常小。对于大多数应用程序来说,风险可以忽略不计,但如果您要生成数十亿个 UUID 或在高度敏感的环境中运行,则应该实施冲突检测。
使用 UUID 进行外部引用:在 URL 或 API 中公开 ID 时,优先使用 UUID 而不是顺序 ID。这增强了安全性并使用户更难预测资源 ID。
以本机格式存储 UUID:使用数据库的本机 UUID 类型来存储 UUID,而不是字符串。这可以减少存储空间并提高查询性能。
选择正确的 UUID 版本:在大多数情况下,uuid4()(基于随机的 UUID)是在 Web 应用程序中生成唯一标识符的最佳选择。但是,如果您需要确定性生成的 UUID,您可以考虑 uuid3() 或 uuid5() (基于命名空间的 UUID)。
验证 UUID:从用户输入接受 UUID 时,请始终验证它们以确保它们在处理前格式正确。在Python中,您可以使用UUID对象来检查字符串的有效性。
def is_valid_uuid(uuid_to_test, version=4): try: uuid_obj = uuid.UUID(uuid_to_test, version=version) return str(uuid_obj) == uuid_to_test except ValueError: return False # Example usage print(is_valid_uuid("66e69275-c6bc-800c-90a6-2f41cb991502")) # True print(is_valid_uuid("invalid-uuid-string")) # False
UUID 是用于在分布式系统中生成唯一标识符并确保 Web 应用程序安全性的强大工具。它们可以帮助您避免数据库迁移期间的数据冲突、可预测的 ID 攻击和 ID 冲突等问题。通过了解并遵循 UUID 的最佳实践,您可以构建更强大、可扩展且安全的后端系统。
请记住使用适当的 UUID 版本,将它们正确存储在数据库中,并注意它们的潜在风险。有了这些技巧,您将能够在项目中有效地处理 UUID!
如果您对 UUID 有任何疑问或其他提示,请随时在下面发表评论!快乐编码!
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3