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

SQLAlchemy如何对加密列执行LIKE模糊查询?

加密列模糊查询的问题解决方法

问题原因

你用EncryptedType把字段加密成BLOB存储后,数据库里存的是加密后的二进制数据。当你执行like查询时,SQLAlchemy会直接把%Vholran%作为条件发给数据库,数据库是对加密后的BLOB做模糊匹配,而不是明文,自然找不到结果。而精确匹配能生效,是因为SQLAlchemy会先把你传入的明文'Vholran'加密,再和数据库里的加密值做对比,匹配逻辑是对的。

可行解决方案

1. 客户端过滤(简单直接,小数据量适用)

先把所有用户数据查出来,在Python代码里对明文做模糊匹配:

name_to_look = 'Vholran'
# 先查询所有用户对象
all_users = db.session.query(User).all()
# 在Python端过滤包含目标字符串的记录
matched_users = [user for user in all_users if name_to_look in user.fullname]

这种方法不用改数据库或加密逻辑,但如果用户表数据量很大(比如上万条以上),性能会很差,因为要全表查询并加载所有数据到内存。

2. 改用可搜索的加密方案(大数据量推荐)

如果数据量较大,需要在数据库端实现模糊匹配,得换用支持搜索的加密方式,常见的思路有两种:

(1)盲索引(Blind Index)

针对模糊查询的需求,比如要匹配包含Vholran的记录,可以提前生成fullname所有可能子串的哈希值(加盐后),存到一个单独的字段里。查询时,生成目标字符串的所有子串哈希,再匹配这个索引字段。

示例实现思路:

  • 给User模型加一个fullname_blind_indices字段,类型为db.ARRAY(db.String)或者用单独的关联表存储索引
  • 当保存User时,生成fullname的所有子串(比如长度3以上的子串),每个子串加盐后哈希,存入索引字段
  • 查询时,生成Vholran的所有子串哈希,然后用fullname_blind_indices.any(哈希值)来匹配

注意:要给哈希加盐,避免彩虹表攻击;同时要接受一定的误匹配概率(哈希碰撞),或者用双哈希降低风险。

(2)确定性加密(Deterministic Encryption)

如果只需要前缀模糊匹配(比如Vhol%),可以用确定性加密算法(相同明文加密后得到相同密文),然后把明文的前缀加密后,用like匹配加密后的前缀。但这种加密方式安全性比随机加密低,容易被频率分析攻击,需要权衡安全性和需求。

3. 避免直接在加密BLOB上做数据库端模糊匹配

不要尝试直接对加密后的BLOB字段用like,因为AES加密后的二进制数据是无规律的,子串匹配完全没有意义,只会浪费性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 18:05:27