当我们在日常开发中设置数据表时,经常需要定义一些敏感字段,如:身份证号、手机号、住址、账号密码等信息,对待这些敏感信息,我们必须进行加密存储,以保证数据存储安全。但是,当用户查询个人信息或者后台管理员根据某个条件筛选用户时,敏感信息又需要进行脱密显示。这往往令我们开发者十分头大,不知道如何实现,那接下来我就介绍几种实现方式:
先全部解密再查询
这是一种暴力解法。我们可以把所有加密数据先全部加载到内存中,在内存中对所有数据再进行解密,然后根据条件进行筛选查询,这完全具有可行性。但是,我们需要明白,程序所分到的内存是有限的,不可能无限大,如果数据库中的数据非常多时,全部加载到内存中进行解密查询,这很容易发生内存溢出,因此不推荐使用这种方法。
图解:
- 先将数据库中的所有数据加载到内存中,用集合来接收所有对象数据。
- 在内存中,对所有加密数据进行解密,并用解密后的数据替换掉加密数据。
- 将需要查询的条件参数进行传入,然后在内存中根据参数进行查询,最后返回查询结果。
建立明文映射表
这是一种假加密法。我们将加密字段的解密数据与主表的主键建立联系,形成一张映射表。当需要查询时,首先在映射表中进行查询,查询到后再根据查到的主键在主表中进行查询,然后将得到的数据进行脱密显示。这种方法可以很好的避免内存溢出问题,但是能看出这是一种假加密,敏感数据事实上还是明文存储,并没有完全加密,存在一定的数据安全风险。
图解:
- 在数据库中建立主表(user表)和映射表(sys_user_phone_encrypt表),并对两表之间的字段建立映射关系。
- 根据查询条件在映射表中进行模糊查询,如果能查到则返回主表的主键值(映射表中的user_id字段值),然后根据主键值再在user表中进行查询,将查询到的结果进行解密显示;如果查询不到,则返回空值。
使用SQL语句进行解密查询
我们在执行查询时,可以直接对加密字段进行解密,然后再查询,相当于将解密语句嵌入到查询语句中。这种方法实现方式容易,成本小,具有非常明显的优点;但是缺点也很明显,查询字段无法建立索引,不能优化查询,并且在这种方式中,我们还必须知道敏感字段的加密算法。
图解:
- 数据库在执行模糊查询时,先对查询的数据进行解密,然后对比查询条件,如果符合则将该条信息传入内存。
- 在内存中,后台对该信息进行解密,然后进行展示。
设置分词密文映射表
这其实是对“建立明文映射表”的升级。在设计时,我们需要把敏感字段进行分段,然后将分段后的数据加密,加密完成后将数据拼接成字符串并与主表的主键一起放入分词密文映射表,形成映射关系。在查询时,我们首先将查询条件进行加密,然后根据解密后的条件在分词密文映射表中进行查询,得到主键值,最后根据主键值在主表中进行查询并解密显示。
例如,某用户的手机号为12345678900,在存入用户表时,给该用户分配了一个主键,主键值为1001,该用户的手机号分成了“1234”、“2345”、“3456”、“4567”、“5678”、“6789”、“7890”和“8900”八个字段,首先数据库对该八个字段分别进行加密,然后将加密后的八个字段数据进行拼接形成字符串,最后将该用户手机号加密后形成的字符串和该用户主键一起存入分词密文映射表中(只要映射关系正确,分词密文映射表可以同时存储多个加密字段),同时也将该用户手机号加密后形成的字符串存入主表中。如果后台管理员需要查询手机尾号为8900的用户,此时系统首先会对8900进行加密,然后将加密后的字符串在分词密文映射表中进行查询得到主键值,最后根据主键值在主表中进行查询,得到该用户的所有信息。在现在开发中,这种方法被广泛使用。
图解:
- 对敏感数据根据需要进行分段,然后将分段后的数据使用加密算法进行加密,最后将加密后的分段数据按顺序进行拼接,形成一个新字符串数据。
- 将拼接的加密数据存入映射表中,并在映射表与主表之间建立映射关系。
- 当需要查询某数据时,首先系统会把参数进行传入,然后将参数按相同算法进行加密,并在映射表中对参数进行模糊查询,如果查询成功则再根据查询到的主键值在主表中进行查询,最后将查询结果进行解密显示。