我目前的方案是这样的:
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 位数以上。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.