- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
前几天,知识星球中有位小伙伴,问了我一个问题:加密的手机号如何模糊查询?
我们都知道,在做系统设计时,考虑到系统的安全性,需要对用户的一些个人隐私信息,比如:登录密码、身份证号、银行卡号、手机号等,做加密处理,防止用户的个人信息被泄露.
很早之前,CSDN遭遇了SQL注入,导致了600多万条明文保存的用户信息被泄.
因此,我们在做系统设计的时候,要考虑要把用户的隐私信息加密保存.
常见的对称加密算法有 AES、SM4、ChaCha20、3DES、DES、Blowfish、IDEA、RC5、RC6、Camellia等.
目前国际主流的对称加密算法是 AES ,国内主推的则是 SM4 .
无论是用哪种算法,加密前的字符串,和加密后的字符串,差别还是比较大的.
比如加密前的字符串: 苏三说技术 ,使用密钥: 123 ,生成加密后的字符串为: U2FsdGVkX1+q7g9npbydGL1HXzaZZ6uYYtXyug83jHA= .
如何对加密后的字符串做模糊查询呢?
比如:假设查询 苏三 关键字,加密后的字符串是: U2FsdGVkX19eCv+xt2WkQb5auYo0ckyw .
上面生成的两个加密字符串差异看起来比较大,根本没办法直接通过SQL语句中的like关键字模糊查询.
那我们该怎么实现加密的手机号的模糊查询功能呢?
实现这个功能,我们第一个想到的办法可能是:把个人隐私数据一次性加载到内存中缓存起来,然后在内存中先解密,然后在代码中实现模糊搜索的功能.
这样做的好处是:实现起来比较简单,成本非常低.
但带来的问题是:如果个人隐私数据非常多的话,应用服务器的内存不一定够用,可能会出现OOM问题.
还有另外一个问题是:数据一致性问题.
如果用户修改了手机号,数据库更新成功了,需要同步更新内存中的缓存,否则用户查询的结果可能会跟实际情况不一致.
比如:数据库更新成功了,内存中的缓存更新失败了.
或者你的应用,部署了多个服务器节点,有一部分内存缓存更新成功了,另外一部分刚好在重启,导致更新失败了.
该方案不仅可能会导致应用服务器出现OOM问题,也可能会导致系统的复杂度提升许多,总体来说,有点得不偿失.
既然数据库中保存的是加密后的字符串,还有一种方案是使用数据库的函数解密.
我们可以使用MySQL的DES_ENCRYPT函数加密,使用DES_DECRYPT函数解密:
SELECT
DES_DECRYPT('U2FsdGVkX1+q7g9npbydGL1HXzaZZ6uYYtXyug83jHA=', '123');
应用系统重所有的用户隐私信息的加解密都在MySQL层实现,不存在加解密不一致的情况.
该方案中保存数据时,只对单个用户的数据进行操作,数据量比较小,性能还好.
但模糊查询数据时,每一次都需要通过DES_DECRYPT函数,把数据库中用户某个隐私信息字段的所有数据都解密了,然后再通过解密后的数据,做模糊查询.
如果该字段的数据量非常大,这样每次查询的性能会非常差.
我们可以将一个完整的字符串,拆分成多个小的字符串.
以手机号为例:18200256007,按每3位为一组,进行拆分,拆分后的字符串为:182,820,200,002,025,256,560,600,007,这9组数据.
然后建一张表:
CREATE TABLE `encrypt_value_mapping` (
`id` bigint NOT NULL COMMENT '系统编号',
`ref_id` bigint NOT NULL COMMENT '关联系统编号',
`encrypt_value` varchar(255) NOT NULL COMMENT '加密后的字符串'
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='分段加密映射表'
这张表有三个字段:
用户在写入手机号的时候,同步把拆分之后的手机号分组数据,也一起写入,可以保证在同一个事务当中,保证数据的一致性.
如果要模糊查询手机号,可以直接通过encrypt_value_mapping的encrypt_value模糊查询出用户表的ref_id,再通过ref_id查询用户信息.
具体sql如下:
select s2.id,s2.name,s2.phone
from encrypt_value_mapping s1
inner join `user` s2 on s1.ref_id=s2.id
where s1.encrypt_value = 'U2FsdGVkX19Se8cEpSLVGTkLw/yiNhcB'
limit 0,20;
这样就能轻松的通过模糊查询,搜索出我们想要的手机号了.
注意这里的encrypt_value用的等于号,由于是等值查询,效率比较高.
注意:这里通过sql语句查询出来的手机号是加密的,在接口返回给前端之前,需要在代码中统一做解密处理.
为了安全性,还可以将加密后的明文密码,用 * 号增加一些干扰项,防止手机号被泄露,最后展示给用户的内容,可以显示成这样的: 182***07 .
如果除了用户手机号,还有其他的用户隐私字段需要模糊查询的场景,该怎么办?
我们可以将encrypt_value_mapping表扩展一下,增加一个 type 字段.
该字段表示数据的类型,比如:1.手机号 2.身份证 3.银行卡号等.
这样如果有身份证和银行卡号模块查询的业务场景,我们可以通过type字段做区分,也可以使用这套方案,将数据写入到encrypt_value_mapping表,最后根据不同的type查询出不同的分组数据.
如果业务表中的数据量少,这套方案是可以满足需求的.
但如果业务表中的数据量很大,一个手机号就需要保存9条数据,一个身份证或者银行卡号也需要保存很多条数据,这样会导致encrypt_value_mapping表的数据急剧增加,可能会导致这张表非常大.
最后的后果是非常影响查询性能.
那么,这种情况该怎么办呢?
如果数据量多的情况下,将所有用户隐私信息字段,分组之后,都集中到一张表中,确实非常影响查询的性能.
那么,该如何优化呢?
答:我们可以增加模糊查询字段.
还是以手机模糊查询为例.
我们可以在用户表中,在手机号旁边,增加一个encrypt_phone字段.
CREATE TABLE `user` (
`id` int NOT NULL,
`code` varchar(20) NOT NULL,
`age` int NOT NULL DEFAULT '0',
`name` varchar(30) NOT NULL,
`height` int NOT NULL DEFAULT '0',
`address` varchar(30) DEFAULT NULL,
`phone` varchar(11) DEFAULT NULL,
`encrypt_phone` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='用户表'
然后我们在保存数据的时候,将分组之后的数据拼接起来.
还是以手机号为例:
18200256007,按每3位为一组,进行拆分,拆分后的字符串为:182,820,200,002,025,256,560,600,007,这9组数据.
分组之后,加密之后,用逗号分割之后拼接成这样的数据:,U2FsdGVkX19Se8cEpSLVGTkLw/yiNhcB,U2FsdGVkX1+qysCDyVMm/aYXMRpCEmBD,U2FsdGVkX19oXuv8m4ZAjz+AGhfXlsQk,U2FsdGVkX19VFs60R26BLFzv5nDZX40U,U2FsdGVkX19XPO0by9pVw4GKnGI3Z5Zs,U2FsdGVkX1/FIIaYpHlIlrngIYEnuwlM,U2FsdGVkX19s6WTtqngdAM9sgo5xKvld,U2FsdGVkX19PmLyjtuOpsMYKe2pmf+XW,U2FsdGVkX1+cJ/qussMgdPQq3WGdp16Q.
以后可以直接通过sql模糊查询字段encrypt_phone了:
select id,name,phone
from user where encrypt_phone like '%U2FsdGVkX19Se8cEpSLVGTkLw/yiNhcB%'
limit 0,20;
注意这里的encrypt_value用的 like .
这里为什么要用逗号分割呢?
答:是为了防止直接字符串拼接,在极端情况下,两个分组的数据,原本都不满足模糊搜索条件,但拼接在一起,却有一部分满足条件的情况发生.
当然你也可以根据实际情况,将逗号改成其他的特殊字符.
此外,其他的用户隐私字段,如果要实现模糊查询功能,也可以使用类似的方案.
最后说一句,虽说本文介绍了多种加密手机号实现模糊查询功能的方案,但我们要根据实际业务场景来选择,没有最好的方案,只有最合适的.
。
最后欢迎大家加入苏三的知识星球【 Java突击队 】,一起学习.
星球中有很多独家的干货内容,比如:Java后端学习路线,分享实战项目,源码分析,百万级系统设计,系统上线的一些坑,MQ专题,真实面试题,每天都会回答大家提出的问题,免费修改简历,免费回答工作中的问题.
星球目前开通了9个优质专栏:技术选型、系统设计、踩坑分享、工作实战、底层原理、Spring源码解读、痛点问题、高频面试题 和 性能优化.
。
。
加入星球如果不满意,3天内包退.
最后此篇关于加密的手机号,如何模糊查询?的文章就讲到这里了,如果你想了解更多关于加密的手机号,如何模糊查询?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在学习 Javascript,我正在尝试创建一个简单的下拉菜单。我想要的功能的示例可以在 Google 主页的顶部菜单中看到,其中包含“更多”和“设置”下拉菜单。 我有一个使用 onclick()
我尝试捕捉 tinyMce 编辑器的模糊和焦点事件。 我为此找到了以下方法。 ed.onInit.add(function(ed) { tiny
这里完全被难住了。尝试一些很简单的东西,但它不起作用: $("input.input1, textarea.input1").focus(function(){ $(this).addClas
我有以下 jQuery 函数: 提交表单 $(".content").delegate('.entryButton','click', function() {var form = $(this).c
如何使用 jQuery 在焦点/模糊上切换元素的 CSS? $('.answerSpace').bind('blur', function(){ $('.normProf').toggleClass(
在我的 iPhone 应用程序中,我有一个黑白 UIImage。我需要模糊该图像(高斯模糊即可)。 iPhone 显然知道如何模糊图像,如 it does that when it draws sha
这个问题已经有答案了: Blurring an image via CSS? (6 个回答) 已关闭 7 年前。 我有一个场景。我想随着循环的进行模糊我的图像。我怎样才能做到这一点?这是我的代码。
这个错误是在子字符串方法上抛出的,我发现很多线程都在处理这个问题,但我遇到的问题似乎有所不同。我知道如果您的字符串短于子字符串(开始,结束)大小,它会抛出此错误,但在任何内容传递到方法调用之前都会抛出
是否有简单的解决方案可以在 Qt 中为图像添加运动模糊?还没有找到任何关于模糊的好教程。我需要一些非常简单的东西,我可以理解,如果我可以改变模糊角度,那就太好了。 最佳答案 Qt 没有运动模糊过滤器。
我的搜索框在正常状态下很小。焦点对准时,它会展开,并显示一个提交按钮。这样做是为了节省空间。现在,在模糊时,搜索框再次缩小,提交按钮消失。 问题是,通过使提交按钮成为“竞赛”以在正确的位置单击它,对提
您好,我正在使用 PngBitmapEncoder 从 Canvas 在内存中创建图像。 public void CaptureGraphic() { Canvas canvas = new
我已经搜索过谷歌、这个和其他论坛,但无济于事……太棒了,有没有可能有像 onMiddleClick="blur();"这样的东西?在单击鼠标中键时隐藏链接的焦点边框? 最佳答案 $('a').clic
我无法在我的应用程序中正确渲染我的纹理。我使用的艺术品是精确的,并且已经缩放且尺寸合适,但是当我在手机上渲染它时,我的纹理突然不如原始艺术品清晰/精确,我不明白为什么。 有人遇到过这个问题吗? 最佳答
这里有与上述主题相同的问题但没有得到答复 我这里有布局 我需要在底部布局中使用与顶部布局相同的图像,但使用模糊样式 设置 alpha 没有帮助 - TextView 也会影响 如何虚化down布局的背
我已经搜索了一段时间,但到目前为止没有找到适合我需要的东西。 ( This was helpful, but not convincing ) 从两个不同的来源,我得到两个不同的字符串。我想检查较短的
我有这样的代码: var passwordTextBox = angular.element("#password"); passwordTextBox.blur(function()
设置此 JQuery 函数无法正常工作。有时,如果我单击元素,什么也没有发生,并且它会触发隐藏可折叠菜单的功能,如果单击文档上的任意位置,则不会重定向到正确的 href。有什么更好的方法吗? HTML
尝试通过将坐标列表保存到数组来在多个位置裁剪我的图像后,裁剪区域中的字母变得非常模糊,我无法弄清楚原因。 原图看起来像 裁剪后的图像看起来像 题中代码如下: import numpy as np im
我知道我们可以调暗/模糊屏幕,如 this post 所示. 我应该怎么做才能使它的一部分变暗/模糊,使单个(或多个) View 没有任何效果,从而使整个屏幕具有突出显示 View 的效果? 此外,即
如果有人曾经向 digg 提交过故事,它会检查该故事是否已经提交,我假设是通过模糊搜索。 我想实现类似的东西,想知道他们是否使用开源的 php 类? Soundex 不这样做,句子/字符串的长度可达
我是一名优秀的程序员,十分优秀!