你如何使用attr_encrypted的灯具

时间:2014-07-10 10:28:05

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

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

2 个答案:

答案 0 :(得分:0)

有效的解决方案是替换所有&#39; \ n&#39;用&#39; \\ n&#39;并使用双引号。这有效:

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

有更简洁的方法吗?

答案 1 :(得分:0)

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

总之,我有以下步骤:

  1. 使用特定文件扩展名写明文(=未加密)文本夹具(在我的例子中,它是* .yml.noenc)。
  2. 编写rake-task以从普通夹具( .yml.noenc)转换为加密夹具( .yml)。
  3. 让我解释下面的详细信息。

    例如,&#34;消息&#34;模型有两个属性&#39; name&#39;和&#39;身体&#39;需要按如下方式加密:

    class Message < ActiveRecord::Base
      attr_encrypted :name, key: ...
      attr_encrypted :body, key: ...
      ...
    end
    
    1. 按如下方式编写test / fixtures / messages.yml.noenc,其中包含普通名称和正文:
    2. 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:
      2. 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]替换为实际值。

        然后,&#39; rake&#39;或者&#39; rake test&#39;检查messages.yml.noenc和messages.yml之间的文件依赖关系,并在必要之前生成messages.yml,然后进行rake test&#39;。