Using attr_encrypted with rails 7



我们已经将应用程序升级到rails 7,现在我们在attr_encrypted gem上遇到了问题。当我们尝试启动rails服务器/控制台时,我们得到以下错误:

gems/ruby-3.0.2/gems/attr_encrypted-3.1.0/lib/attr_encrypted.rb:176:in `block in attr_encrypted': undefined method `[]=' for nil:NilClass (NoMethodError)

如果我们回到rails 6,错误消失了,有人遇到同样的问题吗?

我终于弄明白是怎么回事了。

Rails 7.0有它自己的加密,attr_encrypted gem和Rails 7都引用变量encrypted_attributes, Rails 7变量优先,使gem无用。有一个关于attr_encrypted gem的PR来修复这个问题,但是这个gem已经好几年没有更新了,我怀疑它现在会更新。

GoRails发布了一个关于如何将数据从使用attr_encrypted迁移到使用rails 7加密的教程。我不想为它付费,所以我查看了git的教程。

他们所做的是在迁移中自己解密数据,并手动更新新的加密字段。

这是他们迁移的链接。https://github.com/gorails-screencasts/migrate-attr_encrypted-to-rails-7-encryption/blob/master/db/migrate/20211005214633_migrate_encrypted_attributes.rb

gemattr_encrypted的新版本4.0.0于2023年4月6日发布,它支持Rails 7。

根据前面的答案,两个方向的完全迁移:

class SwitchToRailsBuiltInEncryption < ActiveRecord::Migration[7.0]
ATTRIBUTES = [
[Account, :password],
[Account, :client_secret],
]
def up
ATTRIBUTES.each do |klass, attribute|
klass.reset_column_information
add_column klass.table_name, attribute, :string, length: 510
klass.all.each do |record|
puts "Processing #{klass} with ID #{record.id}"
if record.send("encrypted_#{attribute}").present?
encrypted_value = record.send("encrypted_#{attribute}")
iv = record.send("encrypted_#{attribute}_iv")
value = decrypt(encrypted_value, iv)
record.update!(attribute => value)
end
end
remove_column klass.table_name, "encrypted_#{attribute}"
remove_column klass.table_name, "encrypted_#{attribute}_iv"
end
end
def down
ATTRIBUTES.each do |klass, attribute|
add_column klass.table_name, "encrypted_#{attribute}", :string, length: 510
add_column klass.table_name, "encrypted_#{attribute}_iv", :string, length: 510
klass.all.each do |record|
puts "Processing #{klass} with ID #{record.id}"
if record.send(attribute).present?
encrypted_value, iv = encrypt(record.send(attribute))
record.update!("encrypted_#{attribute}" => encrypted_value, "encrypted_#{attribute}_iv" => iv)
end
end
remove_column klass.table_name, attribute
end
end
# based on https://github.com/gorails-screencasts/migrate-attr_encrypted-to-rails-7-encryption/blob/master/db/migrate/20211005214633_migrate_encrypted_attributes.rb
# as suggested by https://stackoverflow.com/questions/72096672/using-attr-encrypted-with-rails-7
def decrypt(encrypted_value, iv)
value = Base64.decode64(encrypted_value)
cipher = OpenSSL::Cipher.new("aes-256-gcm")
cipher.decrypt
cipher.key = Rails.application.credentials.key
cipher.iv = Base64.decode64(iv)
cipher.auth_tag = value[-16..]
cipher.auth_data = ""
cipher.update(value[0..-17]) + cipher.final
end
def encrypt(value)
cipher = OpenSSL::Cipher.new("aes-256-gcm")
cipher.encrypt
cipher.key = Rails.application.credentials.key
iv = cipher.random_iv
cipher.auth_data = ""
encrypted_value = cipher.update(value) + cipher.final
return Base64.encode64(encrypted_value + cipher.auth_tag), Base64.encode64(iv)
end
end

相关内容

  • 没有找到相关文章

最新更新