在 ruby/ActiveRecord 中生成类似 Instagram 或 Youtube 的不可猜测的字符串 ID [英] Generating an Instagram- or Youtube-like unguessable string ID in ruby/ActiveRecord
问题描述
在创建给定 ActiveRecord 模型对象的实例后,我需要生成一个较短(6-8 个字符)的唯一字符串,用作 URL 中的标识符,采用 Instagram 照片 URL 的样式(例如 http://instagram.com/p/P541i4ErdL/,我只是把它混为 404)或 Youtube 的视频 URL(例如 http://www.youtube.com/watch?v=oHg5SJYRHA0).
Upon creating an instance of a given ActiveRecord model object, I need to generate a shortish (6-8 characters) unique string to use as an identifier in URLs, in the style of Instagram's photo URLs (like http://instagram.com/p/P541i4ErdL/, which I just scrambled to be a 404) or Youtube's video URLs (like http://www.youtube.com/watch?v=oHg5SJYRHA0).
这样做的最佳方法是什么?重复创建随机字符串是否最简单直到它是独一无二的?有没有一种方法可以散列/混洗整数 id,使用户无法通过更改一个字符来破解 URL(就像我在上面的 404'd Instagram 链接中所做的那样)并最终获得新记录?>
What's the best way to go about doing this? Is it easiest to just create a random string repeatedly until it's unique? Is there a way to hash/shuffle the integer id in such a way that users can't hack the URL by changing one character (like I did with the 404'd Instagram link above) and end up at a new record?
推荐答案
你可以这样做:
random_attribute.rb
module RandomAttribute
def generate_unique_random_base64(attribute, n)
until random_is_unique?(attribute)
self.send(:"#{attribute}=", random_base64(n))
end
end
def generate_unique_random_hex(attribute, n)
until random_is_unique?(attribute)
self.send(:"#{attribute}=", SecureRandom.hex(n/2))
end
end
private
def random_is_unique?(attribute)
val = self.send(:"#{attribute}")
val && !self.class.send(:"find_by_#{attribute}", val)
end
def random_base64(n)
val = base64_url
val += base64_url while val.length < n
val.slice(0..(n-1))
end
def base64_url
SecureRandom.base64(60).downcase.gsub(/W/, '')
end
end
Raw
user.rb
class Post < ActiveRecord::Base
include RandomAttribute
before_validation :generate_key, on: :create
private
def generate_key
generate_unique_random_hex(:key, 32)
end
end
这篇关于在 ruby/ActiveRecord 中生成类似 Instagram 或 Youtube 的不可猜测的字符串 ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!