当前位置:

首页 > 编程开发 > Rails实现字段加密存储

Rails实现字段加密存储

在Rails中,利用ActiveSupport::MessageEncryptor实现字段加密,结合ActiveRecord的serialize机制定义自定义Serializer,使敏感字段存入时自动加密、读取时自动解密,业务层无需关注加密细节。同时需注意密钥安全管理和旧数据的平滑迁移。

在 Rails 应用中处理敏感字段,比如用户手机号、地址、姓名这些信息,直接以明文形式存进数据库多少让人有些不放心。一个常见的做法是:存储前,先把数据加密再写入;读取后,再用对应的密钥解密还原。

这其实来自一个非常实用的思路:数据在落盘那一刻就应该是密文,业务层拿到的则是解密后的原文,整个过程对上层代码完全透明。

那么,在 Rails 框架下怎么把这个流程做得既安全又干净?

核心工具:ActiveSupport::MessageEncryptor

这个类是 Rails 基于 OpenSSL 封装出来的一个加密解密工具箱,用法很直接。你只需要先生成一个密钥,然后实例化一个加密器,接下来就能对任意对象进行加密并签名验证了。举个例子:

salt = SecureRandom.random_bytes(64)
key  = ActiveSupport::KeyGenerator.new('password').generate_key(salt) # => "x89xE0x156xAC..."
crypt = ActiveSupport::MessageEncryptor.new(key)            # => #
encrypted_data = crypt.encrypt_and_sign('my secret data')       # => "NlFBTTMwOUV5UlA1QlNEN2xkY2d6eThYWWh..."
crypt.decrypt_and_verify(encrypted_data)                # => "my secret data"

这套组合拳打下来,加密后的数据带着签名,无论是防篡改还是防泄露都有保障。但真正让它好用起来的,是接下来这个机制。

串联 ActiveRecord:serialize 的妙用

Rails 里有个 serialize 类方法,可以告诉模型某个字段在入库前和出库后应该经历怎样的转换。比如你可以直接声明一个字段存成 Hash 类型:

class User < ActiveRecord::Base
 serialize :preferences, Hash
end

user = User.new
user.preferences = {
 gender: 'male',
 age: 18
}
user.sa ve!

当你设置 serialize :preferences, Hash 时,Rails 会在写入前自动把 Hash 序列化成 YAML 字符串,读取后再反序列化回 Ruby 对象。这个流程其实就是我们想要的“自动处理”模型。

更灵活的是,Rails 允许你定义自己的 Serializer。只要实现 .load 和 .dump 两个类方法,就可以完全控制序列化和反序列化的逻辑。类似这样:

class CustomerSerializer
 def self.load(value)
  value.to_s.blank? ? "" : JSON.parse(value)
 end

 def self.dump(value)
  (value || {}).to_json
 end
end

class User < ActiveRecord::Base
 serialize :preferences, CustomerSerializer
end

在这个基础上,把加密解密逻辑放进自定义 Serializer 里,就水到渠成了。

实战:字段加密 Serializer 实现

结合 ActiveSupport::MessageEncryptor 和 serialize,我们直接实现一个能自动加密和解密的 Serializer:

class EncryptedStringSerializer
 def self.load(value)
  value.to_s.blank? ? '' : decrypt(value)
 end

 def self.dump(value)
  encrypt(value || '')
 end

 private

 def self.encrypt(value)
  encryptor.encrypt_and_sign(value)
 end

 def self.decrypt(value)
  encryptor.decrypt_and_verify(value)
 end

 def self.encryptor
  @encryptor ||= ActiveSupport::MessageEncryptor.new(Settings.message_encryptor_key)
 end
end

class UserAddress < ActiveRecord::Base
 serialize :phone, EncryptedStringSerializer
 serialize :first_name, EncryptedStringSerializer
 serialize :last_name, EncryptedStringSerializer
 serialize :country, EncryptedStringSerializer
 serialize :state, EncryptedStringSerializer
 serialize :city, EncryptedStringSerializer
 serialize :address1, EncryptedStringSerializer
 serialize :address2, EncryptedStringSerializer
 serialize :zipcode, EncryptedStringSerializer
end

这样,当 UserAddress 实例的任何一个字段被赋值时,.dump 会被触发,自动加密存储;从数据库读取时,.load 自动解密。业务代码里完全不需要关心加密细节。

可以改进的点

不过这个方案有两个地方值得再琢磨一下:

1. 加解密用的 KEY 是否过于简单?

这里直接用配置项 Settings.message_encryptor_key 初始化了加密器。生产环境中,密钥的管理最好能纳入更严格的体系,比如使用环境变量、密钥管理服务或者定期轮换策略。硬编码在配置里,一旦泄露就全线失守。

2. 针对现有数据,如何平滑过渡?

如果数据库里已经存了大量明文数据,直接加上加密 Serializer 会导致所有旧数据读取时解密失败。需要设计数据迁移脚本:分批读出来加密再写回去,或者采用读时兼容、写时加密的策略,逐步完成数据的更新。这在生产环境切换时需要格外小心。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发
相关文章 更多
Ruby日期时间的比较,日期转换等时间日期处理方法大全
Ruby日期时间的比较,日期转换等时间日期处理方法大全

Ruby日期时间处理主要依赖Date、Time和DateTime三个类。Date仅处理日期,Time可处理日期时间,DateTime是Date子类且效率最高。三者支持创建、字符串转换、比较、加减、时区处理及类型互转。Date与DateTime严格校验无效日期,Time则自动进位。常用操作包括构建、解析、格式化及与数值转换。

Ruby信号处理详解
Ruby信号处理详解

Ruby中Process.kill方法发送信号,signal参数可为整数或符号名指定信号类型,pid参数为正数时发送给指定进程,为0时发送给同组所有进程,为负数时发送给对应进程组(绝对值)。

深入分析Ruby 变量
深入分析Ruby 变量

Ruby变量以命名前缀区分五种类型:全局变量($)可跨类访问但副作用大;实例变量(@)为对象私有数据;类变量(@@)在继承链共享;局部变量(小写/下划线)作用域受限;常量(大写)不可重赋值。伪变量如self、nil不可修改。未初始化变量通常为nil,常量赋值会触发警告。

ruby中并发并行与全局锁详解
ruby中并发并行与全局锁详解

Ruby全局锁(GIL)使多线程在CPU密集型任务中无法并行提速,但IO操作可并发切换。通过厨师比喻和代码示例,阐释了顺序执行与多线程的差异,强调并发不等于并行。

ruby on rails中Model的关联详解
ruby on rails中Model的关联详解

Rails中Model关联需在两端声明,遵循命名惯例:belongs_to后跟单数,has_many后跟复数。一对多通过外键实现,如妈妈与儿子;多对多借助中间表,如学生与老师通过课程表关联。掌握这些基础可高效处理复杂关联。

使用RVM实现控制切换Ruby/Rails版本
使用RVM实现控制切换Ruby/Rails版本

RVM能自由切换Ruby与Rails版本,避免反复重装。通过rvminstall安装指定Ruby版本,用rvmlist查看已安装版本,切换并设为默认。创建gemset绑定Ruby版本,再安装不同Rails版本,即可灵活切换,实现多项目环境隔离。

Ruby 中的 module
Ruby 中的 module

module_function将模块的实例方法复制到单例类,原方法变为私有,仅能通过模块名调用。extendself不改变可见性,public方法既可通过模块名也可通过实例调用。两者均用于暴露模块级方法,但权限不同。

Ruby是什么以及如何使用
Ruby是什么以及如何使用

Ruby是松本行弘于1993年创造的纯面向对象动态语言,融合Smalltalk、Perl和Python精髓,语法简洁易读,一切皆对象。开源解释型跨平台,适合Web开发和脚本编写,可扩展性强,支持多种数据库及GUI工具,是RubyonRails框架的核心语言之一。

Ruby on rails安装后去掉DL is deprecated,please use Fiddle警告信息的方法【测试可用】
Ruby on rails安装后去掉DL is deprecated,please use Fiddle警告信息的方法【测试可用】

在RubyonRails框架中,安装后执行命令时常会出现“DLisdeprecated,pleaseuseFiddle”警告。具体解决方法如下:首先找到Ruby安装目录下的lib/ruby/2.1.0文件夹,进入后找到其中的dl.rb文件,使用文本编辑器打开该文件,定位到含有warn的那一行,在行首添加井号#注释掉该行,保存文件后警告立即消失。

ruby 正则表达式详解及示例代码
ruby 正则表达式详解及示例代码

Ruby正则表达式常用语法包括重复次数(*+?)、范围描述符([])、字符类(如\d\w\s)、边界匹配(^$)、分组捕获及转义等元字符,提供非负整数、邮箱、账号等典型匹配模式,广泛用于表单验证与文本处理,便于快速查阅与套用,功能强大。

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
Postman macOS版
Postman macOS版
Mac

Postman是一套面向API全生命周期的开发与测试平台,可在Mac上发送和调试多种协议请求,管理集合、环境及认证信息,并完成脚本测试、模拟服务、监控、文档发布和团队协作。它适合开发、测试及运维人员使用,提供个人免费方案。

Docker Desktop macOS版
Docker Desktop macOS版
Mac

Docker Desktop 是 Docker 官方为 Mac 提供的容器开发环境,集成 Docker Engine、命令行工具、Compose、Build、Kubernetes 与图形化管理界面。

Android Studio macOS版
Android Studio macOS版
Mac

Android Studio 是 Google 面向安卓应用开发提供的官方集成开发环境,基于 IntelliJ IDEA 构建。它整合智能代码编辑、Gradle 构建、界面预览、设备模拟、性能分析、调试测试及 APK 分析等工具。

WINDOWS 更多
Postman Windows版
Postman Windows版
Windows

Postman 是面向 API 全生命周期的开发与协作平台。Windows 桌面版可用于构建和发送 HTTP、GraphQL、gRPC、WebSocket、MQTT 等请求,并提供环境变量、集合、脚本测试、模拟服务、监控、文档及团队工作区等

Docker Desktop Windows版
Docker Desktop Windows版
Windows

Docker Desktop 为 Windows 开发者提供集成式容器环境,内置 Docker Engine、命令行工具、Compose、Build 与 Kubernetes 等组件,可在本机完成镜像构建、容器运行、日志查看和资源管理。

Android Studio Windows版
Android Studio Windows版
Windows

Android Studio 是 Google 面向 Android 应用开发提供的官方集成开发环境,以 IntelliJ IDEA 为基础,集成智能代码编辑、Gradle 构建、设备模拟、界面预览、调试测试及性能分析工具,