这是我正在使用的。令牌不一定要听才能猜测,它更像是一个短 URL 标识符,而不是其他任何东西,我想保持简短。我遵循了在网上找到的一些示例,并且在发生碰撞时,我认为下面的代码将重新创建令牌,但我不太确定。不过,我很想看到更好的建议,因为这感觉有点粗糙。
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,但因为这些是根据用户在应用程序中的操作自动批量创建的(它们放置了本质上是订购并购买代币),让应用程序抛出错误是不可行的。
我想,为了减少冲突的机会,在末尾附加另一个字符串,根据时间生成的东西或类似的东西,但我不希望令牌变得太长。
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
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.
发布评论
评论(12)
Ryan Bates 在他的Railscast 测试版邀请中使用了一些不错的代码。这会生成 40 个字符的字母数字字符串。
Ryan Bates uses a nice little bit of code in his Railscast on beta invitations. This produces a 40 character alphanumeric string.
这可能是一个较晚的响应,但为了避免使用循环,您也可以递归地调用该方法。对我来说,它看起来和感觉都稍微干净一些。
This might be a late response but in order to avoid using a loop you can also call the method recursively. It looks and feels slightly cleaner to me.
本文演示了一些非常巧妙的方法:
https://web.archive.org/web/20121026000606/http://blog.logeek.fr/2009/7/2/creating-small-unique-tokens-in-ruby
我最喜欢的列表是:
There are some pretty slick ways of doing this demonstrated in this article:
https://web.archive.org/web/20121026000606/http://blog.logeek.fr/2009/7/2/creating-small-unique-tokens-in-ruby
My favorite listed is this:
如果你想要一些独特的东西,你可以使用类似这样的东西:
但是这将生成 32 个字符的字符串。
然而还有其他方法:
例如对于像 10000 这样的 id,生成的令牌将像“MTAwMDA=”(并且您可以轻松地解码它的 id,只需使
If you want something that will be unique you can use something like this:
however this will generate string of 32 characters.
There is however other way:
for example for id like 10000, generated token would be like "MTAwMDA=" (and you can easily decode it for id, just make
这可能会有所帮助:
如果您想删除任何特殊字符,而不是放入第一个参数“+/=”,并将任何字符放入第二个参数“0aZ”,并且 15 是此处的长度。
如果您想删除多余的空格和换行符,请添加以下内容:
希望这对任何人都有帮助。
This may be helpful :
If you want to remove any special character than put in first argument '+/=' and any character put in second argument '0aZ' and 15 is the length here .
And if you want to remove the extra spaces and new line character than add the things like :
Hope this will help to anybody.
尝试这种方式:
从 Ruby 1.9 开始,uuid 生成是内置的。使用
SecureRandom.uuid
函数。在 Ruby 中生成指南
这对我很有帮助
Try this way:
As of Ruby 1.9, uuid generation is built-in. Use the
SecureRandom.uuid
function.Generating Guids in Ruby
This was helpful for me
你可以使用 has_secure_token https://github.com/robertomiranda/has_secure_token
使用起来非常简单
you can user has_secure_token https://github.com/robertomiranda/has_secure_token
is really simple to use
创建正确的 mysql、varchar 32 GUID
To create a proper, mysql, varchar 32 GUID
Rails 7 具有此功能内置 。请参阅下面的示例:
Rails 7, has this functionality baked in. See the example below:
我认为令牌应该像密码一样处理。因此,它们应该在数据库中加密。
我正在做这样的事情来为模型生成一个独特的新令牌:
I think token should be handled just like password. As such, they should be encrypted in DB.
I'n doing something like this to generate a unique new token for a model:
-- 2022 年 EOY 更新 --
我回答这个问题已经有一段时间了。以至于我已经有七年没有看过这个答案了。我还看到许多依赖 Rails 来运行业务的组织中使用了这段代码。
说实话,这些天我不会认为我之前的解决方案,或者 Rails 如何实现它,是一个伟大的解决方案。它使用可以通过 PITA 进行调试的回调,本质上是悲观的
-- Update EOY 2022 --
It's been some time since I answered this. So much so that I've not even taken a look at this answer for ~7 years. I have also seen this code used in many organizations that rely on Rails to run their business.
TBH, these days I wouldn't consider my earlier solution, or how Rails implemented it, a great one. Its uses callbacks which can be PITA to debug and is pessimistic ???? in nature, even though there is a very low chance of collision for
SecureRandom.urlsafe_base64
. This holds true for both long and short-lived tokens.What I would suggest as a potentially better approach is to be optimistic ???? about it. Set a unique constraint on the token in the database of choice and then just attempt to save it. If saving produces an exception, retry until it succeeds.
What is the result of this?
SecureRandom.urlsafe_base64(32, false)
?).-- Update --
As of January 9th, 2015. the solution is now implemented in Rails 5 ActiveRecord's secure token implementation.
-- Rails 4 & 3 --
Just for future reference, creating safe random token and ensuring it's uniqueness for the model (when using Ruby 1.9 and ActiveRecord):
Edit:
@kain suggested, and I agreed, to replace
begin...end..while
withloop do...break unless...end
in this answer because previous implementation might get removed in the future.Edit 2:
With Rails 4 and concerns, I would recommend moving this to concern.