我正在尝试手动生成一个小哈希,以混淆我的IDs应用程序ID。
(我已经解释了为什么我要手动这样做,而不是使用真正的散列,比如SHA、MDA,甚至在这个线程中使用编码哈希( hashid ):hashids vs pure random hash in id obfuscation )
这个散列纯粹是随机的:我从字母数字字符串中选择一些数字:
"abcdefghijklmnopqrstuvwxyz1234567890"这是我的代码:
model.rb
class Model< ApplicationRecord
before_save :set_hashid
validates :hashed_id, uniqueness: true
private
def set_hashid
chain = "abcdefghijklmnopqrstuvwxyz1234567890"
numberdigits = 4
until @hash.present? && !Model.exists?(hashed_id: @hash)
@hash = ""
numberdigits.times do
@hash << chain[rand(0..chain.size-1)]
end
end
self.hashed_id = @hash
end
end效果很好。创建一个由chain字符串中的4位数字组成的散列。它给出了36^4= 1.679.616的可能性
我的模型(最终应该达到1.000.000 )是非常丰富的。
当hashed_id字段中对模型的搜索返回false时,哈希就会传递。
虽然有两个问题:
1 :我的数据库是空的,所以它非常快。但是,当该列有100万条记录时,索引列中4位散列的搜索时间是多少?有什么方法可以预测到这一点吗?(除了找到一个类似的虚拟桌子,我可能很难)。
2st : --我使用uniqueness强制执行验证,所以我想搜索这个散列是在中进行的,但是在强制执行冗余的验证时也是这样。虽然我热衷于保持验证,以防类似的散列在同一时刻与另一个用户通过测试(非常不可能,但谁知道)。有没有一种不同的方法,这样就不需要额外的搜索和验证了?
发布于 2017-11-24 19:19:33
require 'secure_random'
class Model < ApplicationRecord
before_validation :set_hashid!, unless: -> { self.hash_id }
def set_hashid!
begin
self.hashed_id = SecureRandom.hex(2)
end while self.class.exists?(hashed_id: self.hashed_id)
end
endbegin ... while condtion至少运行该块一次,并在可能发生冲突的情况下重复运行self.hashed_id = SecureRandom.hex(2)。
2是SecureRandom.hex使用的以位为单位的长度(它给出的长度为4)。
唯一性验证不会提供任何额外的值,因为它只是检查带有该值的记录是否存在,并且您已经在回调中检查该记录。应用程序级别的验证也很容易受到您试图对抗的竞争条件的影响。
相反,这应该由数据库中的唯一索引强制执行。
您还可以创建Postgres函数并使用它生成随机字符串,并在触发器中使用它来设置值。但我会从这个开始,并研究一下,当表演实际上是一个问题的时候。
https://stackoverflow.com/questions/47477695
复制相似问题