我正在使用此
生成令牌SET @Token = CAST(CRYPT_GEN_RANDOM(16) AS UNIQUEIDENTIFIER)
该令牌将在URL中显示,并且应该是唯一的。
使用它是个好主意吗?
答案 0 :(得分:4)
以这种方式生成的“GUID”不是真正的GUID,因为保留用于指示GUID的变体和版本的GUID中的位也将是随机的。在实践中,大多数工具根本不关心或查看GUID的位,但可以想象某些系统或未来版本将出现GUID位模式的问题无效。碰撞不是你必须担心的,因为剩下的部分在你的结尾是随机的,但这仍然是丑陋的。
对于(加密)随机GUID,您需要一个版本为4的GUID,变量1.四个位表示版本,两个表示变量1,留下122个随机位,这应该是充足的。在T-SQL中正确设置这些位并不直观,但可行:
SELECT CONVERT(UNIQUEIDENTIFIER,
CRYPT_GEN_RANDOM(7) +
-- Set version = 4
CONVERT(BINARY(1), (CRYPT_GEN_RANDOM(1) & 15) | 64) +
-- Set variant = 1
CONVERT(BINARY(1), (CRYPT_GEN_RANDOM(1) & 63) | 128) +
CRYPT_GEN_RANDOM(7)
)
位和字节的位置不直观,因为SQL Server对它们的编码是weird。
还要考虑以下备选方案:
NEWID()
作为令牌,其中几乎不用担心攻击者可能猜到下一个值,或者如果他们这样做,安全性就不会受到损害。请记住,这通常至少需要能够随意生成GUID块,并且最坏的情况是访问生成GUID的机器的内存。前者可以是速率限制的,后者意味着它可能是游戏结束。SELECT CONVERT(CHAR(32), CRYPT_GEN_RANDOM(16), 2)
获得(转换回SELECT CONVERT(BINARY(16), @s, 2)
)。字符串比GUID更容易传递,因此很难理解为什么你在这里绝对需要一个GUID。你还可以获得6个随机性。 BINARY(16)
列与UNIQUEIDENTIFIER
的大小相同,因此存储也不是问题。 (但您可能希望考虑使用字符串列,以便将来为新的令牌格式留出空间。)