Rails3使用attr_encrypted 1.2.1偶发encrypted_private_key存空值问题
attr_encrypted 1.2.1 + Rails 3 偶发encrypted_private_key存空值原因排查
以下是该版本组合下最常见的偶发空值原因:
- 动态密钥执行时序异常:你配置的加密密钥是依赖
device.log返回值的proc,attr_encrypted 1.2.1版本的加密逻辑会在private_key赋值时触发预加密,如果此时log属性还未完成赋值、或是log方法返回空值,加密密钥为空时加密逻辑会直接返回nil,后续保存时就会把空值写入encrypted_private_key字段。偶发是因为log字段的赋值时序在不同执行路径下不一致,有时赋值早于private_key赋值,有时晚于。 - Rails 3 脏属性追踪适配bug:attr_encrypted 1.2.x版本对Rails 3的ActiveRecord脏追踪机制适配存在缺陷,偶发场景下
private_key的变更没有被识别为脏属性,加密后的encrypted_private_key没有被加入到待写入的属性列表中,最终数据库层面该字段写入默认值nil。 - 模型回调顺序冲突:如果Device模型中还定义了其他
before_save/before_create回调,且回调顺序早于attr_encrypted内置的加密回调,当这些回调中执行了重置属性、跳过变更检测的操作,会导致加密逻辑没有执行,最终字段存空。 - 实例状态残留问题:如果代码中存在复用Device实例、或是事务回滚后继续使用原有实例的场景,attr_encrypted 1.2.1版本内部缓存的加密后值会被异常清空,再次保存时就会写入nil。
临时修复建议
- 调整属性赋值顺序,在赋值
private_key之前确保log属性已经赋值完成,同时给密钥proc增加空值兜底逻辑,避免密钥为空 - 升级attr_encrypted到1.3.x系列中兼容Rails 3的最高版本,修复脏追踪适配问题
- 检查模型回调顺序,确保attr_encrypted的加密回调优先级高于自定义业务回调,可以执行
Device._save_callbacks确认回调顺序 - 避免复用已经被保存/回滚过的ActiveRecord实例,新建实例时重新赋值所有属性
内容的提问来源于stack exchange,提问作者user2274074
相关产品推荐
相关产品推荐

