Beego 不支持字段级透明加解密,需在 ORM 层通过 BeforeInsert/AfterSelect 钩子手动加密敏感字段,并配合哈希索引实现查询;禁止硬编码密钥,不可用 AES_DECRYPT 等函数直接参与 Filter 查询。

Beego 本身不提供开箱即用的字段级透明加解密能力,也无法像 Mycat 那样在中间件层拦截 SQL 实现无感脱敏。若你正打算在 Beego 项目中对身份证、手机号等敏感字段做加密存储,必须在 ORM 层或模型层主动介入——这不是配置开关能解决的事,而是要明确控制「何时加密」「加密谁」「怎么查」。
Beego 中如何对 struct 字段自动加解密
Beego 的 orm.RegisterModel 注册模型后,所有 Insert/Read/Update 操作都会走其 ORM 流程,但不会自动处理字段内容。你需要手动干预序列化/反序列化环节:
- 在模型 struct 中将敏感字段标记为
orm:"-"(跳过 ORM 映射),改用私有字段 + 自定义 getter/setter - 使用
BeforeInsert和AfterSelect回调钩子,在数据落库前加密、查出后解密 - 避免在
BeforeUpdate中重复加密:若字段已加密,再次加密会导致二次密文,查询失败 - 加密密钥不能硬编码在代码里,建议从环境变量或 KMS 服务加载,例如
os.Getenv("ENCRYPT_KEY")
加密后还能用 QueryTable().Filter() 查询吗
不能直接用明文条件查加密字段。比如你存的是 AES 加密后的身份证号,Filter("id_card", "11010119900307281X") 必然查不到——数据库里存的是密文字符串。
- 如需模糊匹配(如姓氏+年份),得在加密前做标准化预处理,再对预处理结果加密,查询时也走同样流程
- 如需精确匹配,可额外建一个哈希索引字段(如
id_card_hash = sha256(明文)),用于等值查询,主字段仍加密存储 - Beego 不支持自定义 SQL 函数注入到
Filter条件中,所以别试图写Filter("AES_DECRYPT(id_card, %s)", key)—— 这会报错或被 SQL 注入过滤掉
Beego + MySQL 实现列加密的兼容性陷阱
MySQL 5.7+ 提供了 AES_ENCRYPT/AES_DECRYPT 函数,但 Beego ORM 默认不信任这些函数返回值类型,且无法在 Insert 时把函数当值传入。
- 若强行用
o.Raw("INSERT INTO user (id_card) VALUES (AES_ENCRYPT(?, ?))", plain, key).Exec(),就绕过了 ORM 生命周期,BeforeInsert钩子失效 - MySQL 的
AES_ENCRYPT返回VARBINARY,而 Beego 映射到 string 时可能产生乱码或截断,需显式CONVERT(... USING utf8mb4) - 不同 MySQL 版本默认加密模式不同(5.7 是 ECB,8.0+ 默认是 CBC),跨版本迁移易出解密失败,建议统一指定模式,如
AES_ENCRYPT(?, ?, ?)三参数用法
created_by)是否也要脱敏?这些点一旦漏掉,加密就只是心理安慰。


















