You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在数据库迁移中正确使用attr_encrypted gem

问题分析与解决方案

旧数据未加密的原因及修复

迁移中直接通过user.email = user.o_email再save无法触发加密,核心原因是迁移执行时User模型的attr_encrypted配置未被正确加载,模型属性变更后ORM映射逻辑也未同步,导致加密回调不生效。

修复迁移代码

修改encrypt_data方法,手动在迁移中加载attr_encrypted配置,并强制触发加密逻辑(跳过验证避免干扰):

def encrypt_data
  # 确保User模型在迁移中加载attr_encrypted配置
  User.class_eval do
    attr_encrypted :email, key: ENV['SECRET_KEY_BASE'].scan(/../).map { |x| x.hex }.pack('C*')
  end

  User.find_each do |user|
    user.email = user.o_email
    user.save!(validate: false) # 跳过验证,确保数据能被保存
  end
end

另一种更直接的方式是手动加密并写入字段,绕开模型回调:

def encrypt_data
  cipher = ActiveSupport::MessageEncryptor.new(ENV['SECRET_KEY_BASE'].scan(/../).map { |x| x.hex }.pack('C*'))
  
  User.find_each do |user|
    encrypted_value = cipher.encrypt_and_sign(user.o_email)
    # 拆分加密值和IV(attr_encrypted默认用--分隔加密值与IV)
    encrypted_email, iv = encrypted_value.split('--')
    
    user.update_columns(
      encrypted_email: encrypted_email,
      encrypted_email_iv: iv
    )
  end
end

重启控制台后无法读取user.email的原因及修复

该问题大概率是解密密钥不一致或环境变量未正确加载导致:

  • 检查控制台重启后ENV['SECRET_KEY_BASE']的值是否和创建用户时一致,可在控制台执行puts ENV['SECRET_KEY_BASE']确认。
  • 确认密钥生成逻辑正确:ENV['SECRET_KEY_BASE']需是符合长度要求的十六进制字符串(比如AES-256需要64位十六进制字符,对应32字节二进制密钥),转换后的二进制密钥需和attr_encrypted配置完全匹配。
  • 若用dotenv管理环境变量,确保控制台启动时自动加载了.env文件(比如通过rails c -e development启动,而非手动启动Ruby控制台)。

额外注意事项

  • 迁移前务必备份数据,避免操作失误导致数据丢失。
  • 迁移完成后可通过User.first.encrypted_email对比新旧用户的加密字段格式,确认旧数据加密是否成功。

内容的提问来源于stack exchange,提问作者MZaragoza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:42:18