我目前的方案是这样的:
1 、手机号经过 AES-GCM 对称加密后保存到数据库,每次加密会随机生成向量 IV ,保存到数据库的值是“向量 IV:密文”,秘钥是全局唯一的(保存在 nacos 中)。
2 、为了支持手机号模糊搜索,我利用了项目中现成的 es ,文档的结构如下:
@Data
@Document(indexName = "user_phone_index")
public class UserPhoneDocument {
@Id
private String id; // 与 MySQL 的 userId 一致
@Field(type = FieldType.Keyword)
private Long userId;
/**
* 带位置的 N-Gram HMAC 盲索引数组(对 "位置:四位切片" 哈希),必须为 keyword 类型。
* 例:0:1381 、1:3812 → 各自 HMAC
*/
@Field(type = FieldType.Keyword)
private List<String> phoneTokens;
// 存储完整手机号的 HMAC (用于精确搜索)
@Field(type = FieldType.Keyword)
private String phoneFullHash;
}
phoneTokens 和 phoneFullHash 都会用全局唯一的 hmac key (保存在 nacos )进行哈希。
phoneTokens 是一个滑动切片,固定四位,每次向右滑动一位。
这样设置以后,就可以做到模糊搜索,但要求搜索时至少输入 4 位数以上。
