【问题标题】:Rails - Creating a UID for a ModelRails - 为模型创建 UID
【发布时间】:2010-11-19 15:53:13
【问题描述】:

我有一个模特相册。

我希望 Rails 在创建 PhotoAlbum 时神奇地创建一个 UID。最好是一个很长的数字/字母数字 UID,就好像坏人有这个 UID,他们可以做坏事。

建议:

  • 使用什么来制作 UID
  • 在哪里分配 UID,我可以在架构中将其作为默认值吗?或者像之前一样在模型中,或者在创建之后?这样做的明智方法是什么?

谢谢

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3


    【解决方案1】:

    简单的十六进制键怎么样?只需将伪随机数据和模型数据组合起来,然后将其输入 hexdigest 即可得到一个相当独特的密钥,一个简单的检查就可以确保它确实是唯一的。

    class Album
      before_create :set_uid
    
      protected
        def set_uid
          # This only works before_create obviously, otherwise it would
          # find itself and loop eternally.
          while self.uid.blank? or !Album.find_by_uid(self.uid).blank?
            self.uid = Digest::SHA1.hexdigest("--#{self.title}--#{Time.current.usec}--")
          end
        end
    end
    

    你可以稍微清理一下,但它应该可以工作。

    至于在架构中执行此操作,我猜这取决于您使用的数据库引擎,我不是那里的专家;)

    【讨论】:

    • 我不会使用它 - 但我对安全性感到偏执。如果源代码被公开,黑客可以通过少量测试猜出任何对象的 UID。他们可以在创建条目时简单地尝试每个 usec 组合。
    • 或者...如果有人直接复制并粘贴您的示例,攻击者甚至不需要泄露的源代码,他们拥有您的源代码。假设他们有标题,并且由于 Time.current.usec 只返回一个最大为 999999 的数字,他们只需要检查 999999 种可能性,然后他们就有“秘密”
    • 为了更有趣:让我们假设这实际上是针对一个规模合理的服务——其中创建了数十万张专辑。最终 Time.current.usec 将返回相同的数字。如果专辑的标题相同,并且 usec 值相同,则意味着两个专辑的 uid 值将相同。如果原始海报要创建一个通用的默认专辑名称,或者人们使用“我的派对”之类的东西作为他们的专辑名称,这并不是那么牵强。查找“生日悖论”并尝试jeff.aaron.ca/cgi-bin/birthday
    • 首先,这就是我们构建检查并重新生成 UID(如果它已经存在)的原因。如果我们假设这是大规模公共服务的唯一身份验证,那么您可能是对的,但我经常使用这种验证来处理正式用户帐户过于复杂的情况,例如取消订阅,给人们“一次通行证”以查看页面或类似内容。并非一切都需要顶级安全性。这并不是说不应该考虑它,但这也不意味着这在某些情况下不是一种有效的技术。
    【解决方案2】:

    Rails 默认为您处理数据库 ID。

    不过,您确实不应该隐晦地使用安全性 - 您应该使用插件来处理身份验证和授权,然后即使知道 ID 的坏人也无法做任何事情。

    【讨论】:

      【解决方案3】:

      使用 after_initialize 钩子怎么样?

      我正在假设您不希望 UUID 作为您的主键(否则事情会更复杂)。为了您的目的,我会避免这样做。

      不幸的是,我在没有测试的情况下完成了所有这些操作,因此我不能 100% 确定我没有输入任何拼写错误。如果您遇到任何问题,请随时给我留言。

      首先,您需要将 uuidtools 添加到您的项目中。假设 rails 2,这是在 config/environment.rb

      Rails::Initializer.run do |config|
        ..
        # You can try a later uuidtools version, but this is the one I've worked with
        config.gem "uuidtools", :version => '2.1.1'
        ..
      end
      

      添加上述内容后,运行“sudo rake gems:install”,它应该会下载并安装 gem。

      然后,在您的模型中,添加以下代码:

        validates_length_of :uuid, :is => 36 # Untested.. makes sense to me though
        def after_initialize
          self.uuid ||= UUIDTools::UUID.random_create.to_s
        end
      

      在您创建表的迁移中:

      create table :photo_albums do |t|
        ..
        t.string :id, :limit => 36
        ..
      end
      

      希望对你有帮助。

      奥斯卡

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多