java - 跨多个客户端和服务器生成真正全局唯一的 ID

标签 java javascript flash guid

总结

在 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/

相关文章:

java - 未找到类异常 "java.lang.ClassNotFoundException"Android

javascript - 在 Bootstrap data-show-columns 上触发 jQuery 事件

javascript - Highcharts.js 问题 : is it possible to add blank space from the left and right side of chart that will be visible only during panning?

javascript - localStorage 在 Localhost 上工作,但不在服务器上工作。这可能是什么原因造成的?

php - 在客户端使用网络摄像头录制视频并上传到php服务器

apache-flex - 基于音频的生成艺术的开源库(Flash/ActionScript)

java - 从短链接获取 youtube 重定向链接

java - 升级 JDBC 驱动程序后,隐式类型转换为 Postgres 中的整数失败

Java 8 的流 : why parallel stream is slower?

c# - 调试 AxShockwaveFlash