ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)

前言

1.基础的环境介绍请移步ShardingSphere应用专题–4.1.1版本–sharding jdbc环境搭建(四)
你可以同时打开两个页面,避免因查找原始配置上下翻动。

2.ShardingSphere官方文档更新不及时,很容易踩坑。贴出的4.x版本文档实际是4.0.1版本的,如果你准备使用该版本可以参考官方文档。本文使用的是此时最新的正式版本4.1.1版本,配置与官方文档配置不同。事实上,源码中有非常详细的版本配置文档,本文也是参考4.1.1 tag的源码配置。

3.ShardingSphere各版本差异很大,甚至核心依赖的包名都不一样,使用时,一定要确认使用哪个版本,目前调研的结果:3.x、4.0.1、4.1.1、5.0.0-alpha都存在很大的配置差异

加密背景

安全控制一直是治理的重要环节,数据脱敏属于安全控制的范畴。对互联网公司、传统行业来说,数据安全一直是极为重视和敏感的话题。数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。涉及客户安全数据或者一些商业性敏感数据,如身份证号、手机号、卡号、客户号等个人信息按照相关部门规定,都需要进行数据脱敏。

在真实业务场景中,相关业务开发团队则往往需要针对公司安全部门需求,自行实行并维护一套加解密系统,而当脱敏场景发生改变时,自行维护的脱敏系统往往又面临着重构或修改风险。此外,对于已经上线的业务,如何在不修改业务逻辑、业务SQL的情况下,透明化、安全低风险地实现无缝进行脱敏改造呢?

Apache ShardingSphere根据业界对脱敏的需求及业务改造痛点,提供了一套完整、安全、透明化、低改造成本的数据脱敏整合解决方案。

需求场景分析

对于数据脱敏的需求,在现实的业务场景中一般分为两种情况:

  1. 新业务上线,安全部门规定需将涉及用户敏感信息,例如银行、手机号码等进行加密后存储到数据库,在使用的时候再进行解密处理。因为是全新系统,因而没有存量数据清洗问题,所以实现相对简单。

  2. 已上线业务,之前一直将明文存储在数据库中。相关部门突然需要对已上线业务进行脱敏整改。这种场景一般需要处理三个问题:

    a) 历史数据需要如何进行脱敏处理,即洗数。

    b) 如何能在不改动业务SQL和逻辑情况下,将新增数据进行脱敏处理,并存储到数据库;在使用时,再进行解密取出。

    c) 如何较为安全、无缝、透明化地实现业务系统在明文与密文数据间的迁移。

处理流程详解

整体架构

ShardingSphere提供的Encrypt-JDBC和业务代码部署在一起。业务方需面向Encrypt-JDBC进行JDBC编程。由于Encrypt-JDBC实现所有JDBC标准接口,业务代码无需做额外改造即可兼容使用。此时,业务代码所有与数据库的交互行为交由Encrypt-JDBC负责。业务只需提供脱敏规则即可。作为业务代码与底层数据库中间的桥梁,Encrypt-JDBC便可拦截用户行为,并在改造行为后与数据库交互。

ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第1张图片

Encrypt-JDBC将用户发起的SQL进行拦截,并通过SQL语法解析器进行解析、理解SQL行为,再依据用户传入的脱敏规则,找出需要脱敏的字段和所使用的加解密器对目标字段进行加解密处理后,再与底层数据库进行交互。ShardingSphere会将用户请求的明文进行加密后存储到底层数据库;并在用户查询时,将密文从数据库中取出进行解密后返回给终端用户。ShardingSphere通过屏蔽对数据的脱敏处理,使用户无需感知解析SQL、数据加密、数据解密的处理过程,就像在使用普通数据一样使用脱敏数据。

脱敏规则

在详解整套流程之前,我们需要先了解下脱敏规则与配置,这是认识整套流程的基础。脱敏配置主要分为四部分:数据源配置,加密器配置,脱敏表配置以及查询属性配置,其详情如下图所示:

ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第2张图片

数据源配置:是指DataSource的配置。

加密器配置:是指使用什么加密策略进行加解密。目前ShardingSphere内置了两种加解密策略:AES/MD5。用户还可以通过实现ShardingSphere提供的接口,自行实现一套加解密算法。

脱敏表配置:用于告诉ShardingSphere数据表里哪个列用于存储密文数据(cipherColumn)、哪个列用于存储明文数据(plainColumn)以及用户想使用哪个列进行SQL编写(logicColumn)。

如何理解用户想使用哪个列进行SQL编写(logicColumn)

我们可以从Encrypt-JDBC存在的意义来理解。Encrypt-JDBC最终目的是希望屏蔽底层对数据的脱敏处理,也就是说我们不希望用户知道数据是如何被加解密的、如何将明文数据存储到plainColumn,将密文数据存储到cipherColumn。换句话说,我们不希望用户知道plainColumn和cipherColumn的存在和使用。所以,我们需要给用户提供一个概念意义上的列,这个列可以脱离底层数据库的真实列,它可以是数据库表里的一个真实列,也可以不是,从而使得用户可以随意改变底层数据库的plainColumn和cipherColumn的列名。或者删除plainColumn,选择永远不再存储明文,只存储密文。只要用户的SQL面向这个逻辑列进行编写,并在脱敏规则里给出logicColumn和plainColumn、cipherColumn之间正确的映射关系即可。

为什么要这么做呢?答案在文章后面,即为了让已上线的业务能无缝、透明、安全地进行数据脱敏迁移。

查询属性的配置:当底层数据库表里同时存储了明文数据、密文数据后,该属性开关用于决定是直接查询数据库表里的明文数据进行返回,还是查询密文数据通过Encrypt-JDBC解密后返回。

脱敏处理过程

举个栗子,假如数据库里有一张表叫做t_user,这张表里实际有两个字段pwd_plain,用于存放明文数据、pwd_cipher,用于存放密文数据,同时定义logicColumn为pwd。那么,用户在编写SQL时应该面向logicColumn进行编写,即INSERT INTO t_user SET pwd = ‘123’。ShardingSphere接收到该SQL,通过用户提供的脱敏配置,发现pwd是logicColumn,于是便对逻辑列及其对应的明文数据进行脱敏处理。可以看出**ShardingSphere将面向用户的逻辑列与面向底层数据库的明文列和密文列进行了列名以及数据的脱敏映射转换。**如下图所示:

ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第3张图片

**这也正是Encrypt-JDBC核心意义所在,即依据用户提供的脱敏规则,将用户SQL与底层数据表结构割裂开来,使得用户的SQL编写不再依赖于真实的数据库表结构。而用户与底层数据库之间的衔接、映射、转换交由ShardingSphere进行处理。**为什么我们要这么做?还是那句话:为了让已上线的业务能无缝、透明、安全地进行数据脱敏迁移。

为了让读者更清晰了解到Encrypt-JDBC的核心处理流程,下方图片展示了使用Encrypt-JDBC进行增删改查时,其中的处理流程和转换逻辑,如下图所示。

ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第4张图片

新上线业务

业务场景分析:新上线业务由于一切从零开始,不存在历史数据清洗问题,所以相对简单。

数据加密配置

(1)数据库sql及pom文件

参考ShardingSphere应用专题–4.1.1版本–Sharding-JDBC分库分表(六)的数据库sql及pom文件

(2)添加字段加密环境配置application-sp-encrypt.properties
#打印sql
spring.shardingsphere.props.sql.show=true
#设置单次请求可适用的最大线程数,以决定是线程限制还是内存限制。增大该参数可提高数据库元数据加载速度(默认为1)
spring.shardingsphere.props.max.connections.size.per.query=3

spring.shardingsphere.datasource.names=master

spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://localhost:4406/mydb?characterEncoding=utf-8
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=111


spring.shardingsphere.sharding.tables.bill.key-generator.column=id
spring.shardingsphere.sharding.tables.bill.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.bill.key-generator.props.worker.id=123

spring.shardingsphere.encrypt.tables.bill.columns.bill_name.cipherColumn=bill_name
spring.shardingsphere.encrypt.tables.bill.columns.bill_name.encryptor=encryptor_md5

spring.shardingsphere.encrypt.encryptors.encryptor_md5.type=md5
spring.shardingsphere.encrypt.encryptors.encryptor_md5.props.md5.key.value=123456
(3)配置说明

ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第5张图片

1.逻辑表名(和查询语句中的表别名保持一致)
2.加密字段名,数据库中真实的字段名称

3.加密方式的别名,自定义
4.必须是3中已经定义的解密方式,否则报错
5.真实的加密类型,目前sharding内部支持aes和md5

使用这套配置,Encrypt-JDBC只需将logicColumn和cipherColumn进行转换,底层数据表不存储明文,只存储了密文,这也是安全审计部分的要求所在。如果用户希望将明文、密文一同存储到数据库,只需添加plainColumn配置即可。整体处理流程如下图所示:
ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第6张图片

这里有个误区:

1.比如手机号的数据需要加密入库,按照上图,手机号在get的时候被解析成了明文,但是有的时候,我需要显示的是133****4455这种格式
2.对于有的业务,id在数据库中是明文存储的,而业务希望前台显示是对称加密的(防止暴露业务量)

对于以上的问题,ShardingSphere的Encrypt-JDBC不支持,也无法支持

  • 1中属于业务自己特定的需求,且这种数据传到前端后,就不会根据这个字段返回给后端,因为返回了也无法做逻辑处理使用了,这种需求,本身就应该业务自己去处理,Encrypt-JDBC只关心服务于数据之间的问题。至于显示与服务之间,应该由服务自己去处理。而不是放到数据库中间层

  • 2中的业务不属于数据中间件处理的范畴,他更是服务上层(service filter等)应该做的事,比如强行指定id入库解密密,出库加密,这样就会导致,为了前端显示的需求,增加的加密逻辑,会在整个服务端内部使用,即使是内部getById,都要解密去查,然后返回加密,一来一回白白多了一套加解密。

核心点就是,不要尝试用Encrypt-JDBC处理以上问题,因为以上问题不属于数据中间件的领域,Encrypt-JDBC只做自己领域的事

代码测试

清空下mydb中的数据

(1)插入

ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第7张图片

在这里插入图片描述

插入数据库的数据为加密的数据
在这里插入图片描述

(2)根据id查询

ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第8张图片

这里的账单名称被被解密了。
ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第9张图片
密文查询不到

(3)根据加密字段作为查询条件

直接用page方法,里面可以使用billName查询
ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第10张图片
使用明文可以查询到。这个很符合手机号这种信息,在数据库中是加密的,但是取出来都是解密处理的

如果这个加密的字段是密码呢,使用MD5加密,取出的时候怎么解密?
ShardingSphere应用专题--4.1.1版本--Sharding-JDBC 字段加密之新业务加密(九)_第11张图片
事实上,MD5的解密方法直接将原值返回回来了,那如果AES方式,取出的时候不想解密怎么办?我们可以通过自定义的方式,实现自己业务的逻辑,比如将AES的decrypt方法自定义为不解密的方式(我一时半会没想起有那个场景是需要这样的 -_- !)关于自定义实现加密,看下文中ShardingSphere应用专题–4.1.1版本–Sharding-JDBC 字段加密之自定义加密策略(十一)

总结

整个加密过程仅需要增加简单的配置,即可完成新业务的字段加密。非常简单高效

你可能感兴趣的:(MySQL,集群/分布式,中间件,数据库,mysql,sharding,shardingsphere,字段加密)