【问题标题】:How do you use fixtures with attr_encrypted您如何使用带有 attr_encrypted 的固定装置
【发布时间】:2014-07-10 10:28:05
【问题描述】:

我想测试一个使用attr_encrypted 加密数据库中的秘密的模型

class Thing
  attr_encrypted :secret, encode: true
end

但是当我在夹具中定义秘密时,编码的换行符被转义了。

one:
  encrypted_secret: '<%= Thing.encrypt_secret(SecureRandom.uuid) %>'

即:

'axZFZEknxUSYdUlPhwLBbj8CwSeCW5at2INA98EcCcY7MVFdmXvk7Sb4DZhC\nm6qD\n'

在数据库中存储为:

'axZFZEknxUSYdUlPhwLBbj8CwSeCW5at2INA98EcCcY7MVFdmXvk7Sb4DZhC
 m6qD'

问题是这样会失败:

thing = things(:one)
assert_equal thing, Thing.find_by_secret(thing.secret)

Thing.find_by_secret(thing.secret) 返回 nil,因为生成的 SQL 查询尝试匹配加密密钥的两个版本,但未能获得匹配。

我试过了:

one:
  encrypted_secret: 'axZFZEknxUSYdUlPhwLBbj8CwSeCW5at2INA98EcCcY7MVFdmXvk7Sb4DZhC\nm6qD\n'

但得到相同的结果。

如何配置我的灯具以使用 attr_encrypted?

【问题讨论】:

    标签: ruby-on-rails activerecord fixtures minitest attr-encrypted


    【解决方案1】:

    可行的解决方案是将所有 '\n' 替换为 '\\n' 并使用双引号。这有效:

    one:
      encryped_secret: "<%= Thing.encrypt_secret(SecureRandom.uuid).gsub(/\n/, '\\\\n') %>"
    

    有没有更简洁的方法来做到这一点?

    【讨论】:

      【解决方案2】:

      我在 Rails4 + attr_encrypted + fixture + Minitest 环境下遇到了同样的情况,这里是我的解决方法。

      总的来说,我有以下步骤:

      1. 使用特定文件扩展名(在我的例子中是 *.yml.noenc)编写纯文本(= 未加密)文本装置。
      2. 编写 rake-task 以将普通夹具 (.yml.noenc) 转换为加密夹具 (.yml)。

      让我在下面解释一下细节。

      例如,“消息”模型有两个属性'name'和'body',需要加密如下:

      class Message < ActiveRecord::Base
        attr_encrypted :name, key: ...
        attr_encrypted :body, key: ...
        ...
      end
      
      1. 将 test/fixtures/messages.yml.noenc 编写如下,其中包含纯名称和正文:
      msg1:
        name: Hello
        body: Hello, I am here...
      msg2:
        name: How are you
        body: Good morning, ...
      
      1. 编写如下 rake-task(例如 lib/tasks/encrypt_fixture.rake)将 messages.yml.noenc 转换为 messages.yml:
      require 'active_record/fixtures'
      
      src_yml   = 'test/fixtures/messages.yml.noenc'
      dest_yml  = 'test/fixtures/messages.yml'
      
      task 'test'   => dest_yml
      
      namespace :[MY_APP] do
        desc "generate encrypted fixture"
        file dest_yml => src_yml do |t|
          require Rails.root + 'config/environment'
      
          encrypted_hash  = {}
          for k, v in YAML.load(ERB.new(File.read(Rails.root + src_yml)).result) do
            msg = Message.new(v.merge([ANY ADDITIONAL ATTRS]))
            encrypted_hash[k] = {
              'encrypted_name'    => msg.encrypted_name,
              'encrypted_name_iv' => msg.encrypted_name_iv,
              'encrypted_body'    => msg.encrypted_body,
              'encrypted_body_iv' => msg.encrypted_body_iv,
              [ANY ADDITIONAL KEY_N_VALUE]
            }
          end
      
          File.open(Rails.root + t.name, 'w') do |f|
            f.write(<<EOH)
          #----------------------------------------------------------------------
          # DO NOT MODIFY THIS FILE!!
          #
          # This file is generated from #{src_yml} by:
          #
          #   (edit #{src_yml})
          #   $ rake [MY_APP]:generate_fixture, or
          #   $ rake
          #----------------------------------------------------------------------
      EOH
            f.write(encrypted_hash.to_yaml)
          end
        end
      end
      

      请将 [MY_APP]、[ANY ADDITIONAL ATTRS] 和 [ANY ADDITIONAL KEY_N_VALUE] 替换为实际值。

      然后,“rake”或“rake test”检查messages.yml.noenc和messages.yml之间的文件依赖关系,并在“rake test”之前在必要时生成messages.yml。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-07-08
        • 2012-02-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-04
        相关资源
        最近更新 更多