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 クエリが暗号化されたシークレットの 2 つのバージョンを照合しようとして、一致を取得できないためです。

私が試してみました:

one:
  encrypted_secret: 'axZFZEknxUSYdUlPhwLBbj8CwSeCW5at2INA98EcCcY7MVFdmXvk7Sb4DZhC\nm6qD\n'

しかし、同じ結果が得られます。

フィクスチャを attr_encrypted で動作するように設定するにはどうすればよいですか?

4

2 に答える 2

0

Rails4 + attr_encrypted + Fixture + Minitest 環境で同じ状況に直面しましたが、私の回避策は次のとおりです。

要約すると、次の手順がありました。

  1. 特定のファイル拡張子 (私の場合は *.yml.noenc) を持つプレーン (= 暗号化されていない) テキストのフィクスチャを書き込みます。
  2. プレーンなフィクスチャ ( .yml.noenc) から暗号化されたフィクスチャ (.yml)に変換する rake-task を記述します。

以下、その詳細を説明しよう。

たとえば、「メッセージ」モデルには、次のように暗号化する必要がある 2 つの属性「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 に答える
0

機能する解決策は、すべての '\n' を '\\n' に置き換え、二重引用符を使用することです。これは機能します:

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

これを行うためのよりきちんとした方法はありますか?

于 2014-07-10T10:28:05.003 に答える