Sli*_*k23 154 random guid ruby-on-rails ruby-on-rails-3
这就是我正在使用的.令牌不一定要被猜测,它更像是一个短网址标识符,而不是其他任何东西,我想保持简短.我已经按照我在网上找到的一些例子,如果发生碰撞,我认为下面的代码会重新创建令牌,但我不确定.不过,我很想看到更好的建议,因为边缘感觉有点粗糙.
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
Run Code Online (Sandbox Code Playgroud)
我的令牌的数据库列是一个唯一的索引,我也在validates_uniqueness_of :token
模型上使用,但因为这些是根据用户在应用程序中的操作自动批量创建的(他们下订单并购买令牌,基本上),它是让应用程序抛出错误是不可行的.
我猜,我也可以减少碰撞的几率,在最后添加另一个字符串,根据时间或类似的东西生成的东西,但我不希望令牌太长.
Kru*_*ule 328
- 更新 -
截至2015年1月9日.该解决方案现在在Rails 5 ActiveRecord的安全令牌实现中实现.
- Rails 4和3 -
仅供将来参考,创建安全随机令牌并确保其对模型的唯一性(使用Ruby 1.9和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
Run Code Online (Sandbox Code Playgroud)
编辑:
@kain建议,我同意,在这个答案中替换begin...end..while
,loop do...break unless...end
因为以前的实现可能会在将来被删除.
编辑2:
有了Rails 4和关注点,我建议关注它.
# 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
Run Code Online (Sandbox Code Playgroud)
Nat*_*ird 51
Ryan Bates在他的Railscast中使用了一些不错的代码来发布测试版邀请函.这将生成一个40个字符的字母数字字符串.
Digest::SHA1.hexdigest([Time.now, rand].join)
Run Code Online (Sandbox Code Playgroud)
cor*_*ard 30
在本文中演示了一些非常流畅的方法:
我最喜欢的是这个:
rand(36**8).to_s(36)
=> "uur0cj2h"
Run Code Online (Sandbox Code Playgroud)
Mar*_*Pop 30
这可能是一个迟到的响应,但为了避免使用循环,您也可以递归调用该方法.它看起来和感觉稍微清洁一点.
class ModelName < ActiveRecord::Base
before_create :generate_token
protected
def generate_token
self.token = SecureRandom.urlsafe_base64
generate_token if ModelName.exists?(token: self.token)
end
end
Run Code Online (Sandbox Code Playgroud)
Ess*_*sse 17
如果你想要一些独特的东西,你可以使用这样的东西:
string = (Digest::MD5.hexdigest "#{ActiveSupport::SecureRandom.hex(10)}-#{DateTime.now.to_s}")
Run Code Online (Sandbox Code Playgroud)
但是这将生成32个字符的字符串.
然而,还有其他方式:
require 'base64'
def after_create
update_attributes!(:token => Base64::encode64(id.to_s))
end
Run Code Online (Sandbox Code Playgroud)
例如对于像10000这样的id,生成的令牌就像"MTAwMDA ="(并且您可以轻松地将其解码为id,只需制作
Base64::decode64(string)
Run Code Online (Sandbox Code Playgroud)
Vik*_*Vik 14
这可能会有所帮助:
SecureRandom.base64(15).tr('+/=', '0aZ')
Run Code Online (Sandbox Code Playgroud)
如果你想删除任何特殊字符而不是放在第一个参数'+/='中,并且任何字符放在第二个参数'0aZ'中,15就是这里的长度.
如果你想删除额外的空格和换行符而不是添加以下内容:
SecureRandom.base64(15).tr('+/=', '0aZ').strip.delete("\n")
Run Code Online (Sandbox Code Playgroud)
希望这对任何人都有帮助.
你可以用户has_secure_token https://github.com/robertomiranda/has_secure_token
使用起来非常简单
class User
has_secure_token :token1, :token2
end
user = User.create
user.token1 => "44539a6a59835a4ee9d7b112b48cd76e"
user.token2 => "226dd46af6be78953bde1641622497a8"
Run Code Online (Sandbox Code Playgroud)
创建适当的mysql varchar 32 GUID
SecureRandom.uuid.gsub('-','').upcase
Run Code Online (Sandbox Code Playgroud)