5

我想测试一个使用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?

4

2 回答 2

0

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

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

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

于 2014-07-10T10:28:05.003 回答
0

我在 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。

于 2016-05-15T15:07:03.910 回答