在Rails中创建唯一令牌的最佳方法? [英] Best way to create unique token in Rails?
问题描述
这就是我正在使用的.令牌不必一定要猜测,它更像是一个简短的url标识符,而不是其他任何东西,我想使其简短.我遵循了一些我在网上找到的示例,如果发生碰撞,我认为下面的代码将重新创建令牌,但我不确定.不过,我很好奇看到更好的建议,因为这在边缘上有些粗糙.
Here's what I'm using. The token doesn't necessarily have to be heard to guess, it's more like a short url identifier than anything else, and I want to keep it short. I've followed some examples I've found online and in the event of a collision, I think the code below will recreate the token, but I'm not real sure. I'm curious to see better suggestions, though, as this feels a little rough around the edges.
def self.create_token
random_number = SecureRandom.hex(3)
"1X#{random_number}"
while Tracker.find_by_token("1X#{random_number}") != nil
random_number = SecureRandom.hex(3)
"1X#{random_number}"
end
"1X#{random_number}"
end
我的令牌数据库列是唯一索引,并且我还在模型上使用validates_uniqueness_of :token
,但是由于这些是根据用户在应用程序中的操作自动创建的,因此它们是成批创建的(他们下订单并购买令牌,本质上),让应用抛出错误是不可行的.
My database column for the token is a unique index and I'm also using validates_uniqueness_of :token
on the model, but because these are created in batches automatically based on a user's actions in the app (they place an order and buy the tokens, essentially), it's not feasible to have the app throw an error.
我想,我还可以减少冲突的机会,在末尾附加另一个字符串,这些字符串是基于时间生成的,或者类似的东西,但是我不希望令牌太长.
I could also, I guess, to reduce the chance of collisions, append another string at the end, something generated based on the time or something like that, but I don't want the token to get too long.
推荐答案
-更新-
截至2015年1月9日.该解决方案现已在 Rails 5 中实现.
As of January 9th, 2015. the solution is now implemented in Rails 5 ActiveRecord's secure token implementation.
-Rails 4& 3-
仅供以后参考,创建安全的随机令牌并确保它对于模型是唯一的(使用Ruby 1.9和ActiveRecord时):
Just for future reference, creating safe random token and ensuring it's uniqueness for the model (when using Ruby 1.9 and ActiveRecord):
class ModelName < ActiveRecord::Base
before_create :generate_token
protected
def generate_token
self.token = loop do
random_token = SecureRandom.urlsafe_base64(nil, false)
break random_token unless ModelName.exists?(token: random_token)
end
end
end
@kain ,并且我同意在此答案中用loop do...break unless...end
替换begin...end..while
将来可能会被删除.
@kain suggested, and I agreed, to replace begin...end..while
with loop do...break unless...end
in this answer because previous implementation might get removed in the future.
对于Rails 4和关注点,我建议将其转移到关注点上.
With Rails 4 and concerns, I would recommend moving this to concern.
# app/models/model_name.rb
class ModelName < ActiveRecord::Base
include Tokenable
end
# app/models/concerns/tokenable.rb
module Tokenable
extend ActiveSupport::Concern
included do
before_create :generate_token
end
protected
def generate_token
self.token = loop do
random_token = SecureRandom.urlsafe_base64(nil, false)
break random_token unless self.class.exists?(token: random_token)
end
end
end
这篇关于在Rails中创建唯一令牌的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!