总结
在 flash 和/或 javascript 客户端中真正全局唯一的 ID。 我可以使用当前浏览器/flash 中可用的 RNG 来做到这一点,还是我必须构建一个具有服务器端随机性的复合 ID?
详情
我需要为对象生成全局唯一标识符。我有多个用 java 编写的服务器端“系统”需要能够交换 id;这些系统中的每一个都有一组 flex/javascript 客户端,它们实际上为新对象生成 ID。我需要保证在一组不相关的系统中的全局唯一性;例如,我需要能够合并/同步两个独立系统的数据库。我必须保证这些 id 之间永远不会发生冲突,并且我永远不需要更改对象的 id 一旦创建。我需要能够在 Flash 和 JavaScript 客户端中生成 ID,而无需为每个 ID 联系服务器。只要不经常联系服务器,依赖于某些服务器提供的种子或系统 ID 的解决方案就可以了。最好使用完全断开连接的解决方案。类似地,不需要预先注册系统的解决方案优于依赖中央机构(如 MAC 地址中的 OUI)的解决方案。
我知道显而易见的解决方案是“使用 UUID 生成器”,例如闪存中的 UIDUtil。此函数明确否认全局唯一性。总的来说,我担心依靠 PRNG 来保证全局唯一性。
建议的解决方案
完全依赖客户端中的安全随机数生成器。
Flash 11+ 有 flash.crypto.generateRandomBytes ; Javascript 有 window.crypto 但它很新,在 IE 中不受支持。有类似 sjcl 的解决方案使用鼠标添加熵。
我知道给定一个完美的 RNG,2122 随机 UID 发生碰撞的可能性很小,但我担心我实际上不会在 javascript 中获得这种程度的随机性或闪存客户端。我还担心即使是加密 RNG 的典型用例也与我的不同:对于 session key 等,只要攻击者无法预测冲突,冲突是可以接受的。就我而言,碰撞是完全不能接受的。 我真的应该依赖安全 RNG 的原始输出来获得唯一 ID 吗?
生成一个包含系统、 session 和对象 ID 的复合 ID。
一个明显的实现是在服务器安装时创建一个系统 UUID,保留每个客户端登录 session ID(例如在数据库中),然后将系统和 session ID 发送到客户端,客户端将保留每个- session 计数器。 uid 将是三元组:系统 ID、 session ID、客户端计数器。
我可以想象直接连接这些或使用加密哈希对它们进行哈希处理。我担心散列本身可能会引入冲突,特别是如果散列的输入与输出的大小大致相同。但是散列会掩盖系统 ID 和计数器,这可能会泄露信息。
另一种解决方案不是在安装时生成系统 ID,而是拥有一个分发唯一系统 ID 的中央注册表,有点像 DOI 所做的。然而,这需要更多的协调,但我想这是真正保证全局唯一性的唯一方法。
关键问题
- 基于随机还是复合?
- 包括系统 ID?
- 如果是系统 ID:生成随机系统 ID 还是使用中央注册表?
- 包括时间戳或其他随机数?
- 散列还是不散列?
最佳答案
最简单的答案是使用服务器分配的客户端 ID,该 ID 会随着每个客户端递增,并使用每个客户端上的值,该值会随着该客户端上的每个片段而递增。客户端 ID 和片段 ID 对成为该内容的全局唯一 ID。
另一种简单的方法是在服务器上生成一组唯一的 ID(比如一次 2k),然后将它们分批发送给每个客户端。当客户端用完 ID 时,它会联系服务器以获取更多 ID。
客户端 ID 应该存储在所有服务器都可以访问的中央存储库中。
它可能有助于查看 distributed hashing 的方法用于在对等环境中唯一标识和定位片段。考虑到您有一台可以干预以断言唯一性的服务器,这可能有点矫枉过正。
要回答您的问题,您需要确定增加系统 ID、随机数或哈希值的复杂性会带来的好处。
系统 ID: 系统 ID 通常用于唯一标识域中的系统。因此,如果您不关心用户是谁,或者打开了多少 session ,而只想确保您知道设备是谁,那么请使用系统 ID。这在用户或 session 可能相关的以用户为中心的环境(例如 JavaScript 或 Flash)中通常用处不大。
随机数: 随机数/盐/随机种子将用于混淆或以其他方式扰乱 ID。当您不希望其他人能够猜出 ID 的原始值时,这一点很重要。如果这是必要的,那么最好用私有(private)加密 key 对 ID 进行加密,然后将公共(public)解密 key 传递给需要读取 ID 的每个消费者。
时间戳:考虑到客户端时钟的可变性(即您不能保证它遵守任何时间或时区),时间戳需要被视为此应用程序的伪随机值.
散列:虽然散列通常(滥用)用于创建唯一键,但它们的真正目的是将一个大的(可能是无限的)域映射到一个更小、更易于管理的域。例如,MD5 通常用于根据时间戳、随机数和/或随机数数据生成唯一 ID。实际发生的是 MD5 函数将无限范围的数据映射到 2^128 种可能性的空间中。虽然这是一个巨大的空间,但它不是无限的,所以逻辑告诉你会有(即使只是在理论上)相同的哈希分配给两个不同的片段。另一方面,完美散列尝试为每条数据分配一个唯一标识符,但是如果您只是为每个客户端片段分配一个唯一标识符开始,这是完全没有必要的。
关于java - 跨多个客户端和服务器生成真正全局唯一的 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10697975/