【发布时间】:2011-01-08 16:24:26
【问题描述】:
我在一个网站上有一个表格,其中包含访问者的一些个人信息。我将此信息传递给另一个服务,我需要为这些表单中的每一个分配提交一个 100 个字符的唯一哈希,以便与记录一起存储在数据库中。生成此密钥并确保其唯一性的最佳方式是什么?键自动递增也没关系。
【问题讨论】:
标签: ruby-on-rails hash
我在一个网站上有一个表格,其中包含访问者的一些个人信息。我将此信息传递给另一个服务,我需要为这些表单中的每一个分配提交一个 100 个字符的唯一哈希,以便与记录一起存储在数据库中。生成此密钥并确保其唯一性的最佳方式是什么?键自动递增也没关系。
【问题讨论】:
标签: ruby-on-rails hash
ActiveSupport::SecureRandom.hex(50)
这不是独一无二的机会是天文数字。
替代简单的“不扩展”竞争条件失败解决方案。
class MyModel < ActiveRecord::Base
before_create :assign_unique_token
private
def assign_unique_token
self.unique_token = ActiveSupport::SecureRandom.hex(50) until unique_token?
end
def unique_token?
self.class.count(:conditions => {:unique_token => unique_token}) == 0
end
end
如果您真的想确定,请在列上创建唯一索引,并通过重试来处理 DB 唯一性错误,类似于我上面的实现。
【讨论】:
SecureRandom.hex(n) 将 n 加倍为生成代码中的字符长度(因此对于 Postgres 字符串类型不超过 120 或其他) 2 . 赋值后别忘了保存你的模型! (呃)
Ruby 标准库有一个用于生成 GUID 的模块:
http://ruby-doc.org/stdlib/libdoc/digest/rdoc/classes/Digest/SHA2.html
例子:
Digest::SHA1.hexdigest(Time.now.to_s)
【讨论】:
如果您使用密码,您可以加密始终不同的消息以获得始终不同的密钥:
def encrypt(data, key, cipher_type)
aes = OpenSSL::Cipher::Cipher.new(cipher_type)
aes.encrypt
aes.key = key
aes.update(data) + aes.final
end
>> Base64.encode64(encrypt(Time.now.to_s, "some_key_long_enough_for_the_job", "AES-256-ECB"))
=> "sKJU3qhszV30Ya9vMFvbqIXus+QygICdDyr7UQFWLeM=\n"
【讨论】: