使用Sharding-JDBC加密数据
By: Date: 2020年8月31日 Categories: 程序 标签:

项目在运行过程中,难免会存储一些敏感的信息,如用户手机号,住址,身份证号,银行卡号等等,这些以明文的方式存储在DB中是极其不安全的,尤其当我们的研发,运维都对数据库表拥有权限时,用户敏感信息泄露就可能会在不经意间发生。因此对于安全责任感重于泰山的公司来说,数据加密至关重要。

再来了解下ShardingJdbc数据加密模块:

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

详细这里就不说了,可以看文末的官方文档。在本文的示例中,实际上使用了Mybatis-plus,Druid,但都不影响Sharding-jdbc的配置,下面来看看怎么应用在我们的项目中。

pom.xml配置

<!--数据加密-->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

yml配置

先来看下原来我们DataSource的配置,Springboot在启动时,会为我们用如下的配置自动配置一个数据源:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.jdbc.Driver
    driver-class-name: com.mysql.jdbc.Driver
    platform: mysql
    url: jdbc:mysql://localhost:3306/story_admin?characterEncoding=utf-8
    username: admin
    password: 123456
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT1FROMDUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    filters: stat,wall,log4j
    logSlowSql: true

而当我们使用sharding-jdbc的时候,如果还是用上面的DataSource,那么控制台会告诉你:

Error creating bean with name 'shardingDataSource' defined in class path resource [org/apache/shardingsphere/shardingjdbc/spring/boot/SpringBootConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'shardingDataSource' threw exception; nested exception is java.lang.IllegalArgumentException: Data sources cannot be empty.

这是因为sharding-jdbc需要配置一个叫shardingDataSource的数据源。所以当我们在使用的Sharding-jdbc,4.1.1版本时,则需要将配置做适当的修改。当然了不同版本,dataSource的名称可能不一样,所以根据版本来配置。
同时,在下面加上我们需要给表中的字段进行加密处理的配置部分,完整的配置如下:

spring:
  shardingsphere:
    datasource:     #数据源配置
      names: ds
      ds:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/story_admin?characterEncoding=utf-8
        username: admin
        password: 123456
    encrypt:
      encryptors:
        encryptor_aes:
          #qualifiedColumns: t_user.password
          #加解密器类型,可自定义或选择内置类型:MD5/AES
          type: aes  
          props:
            #属性配置, 注意:使用AES加密器,需要配置AES加密器的KEY属性:aes.key.value
            aes.key.value: cust_aes_key
      tables:
        t_user:                            #表名
          columns:
            mobile:                     #logicColumn逻辑列名称
              # plainColumn: mobile     #存储明文的字段
              cipherColumn: mobile      #存储密文的字段
              encryptor: encryptor_aes  #加解密器名字
    props:
      sql:
        show: true  #是否开启SQL显示,默认值: false
      query:
        with:
          cipher:
            column: true #是否使用密文列查询

来看看sharding-jdbc-spring-boot-starter的自动配置org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration类的部分源码,如下:

@Bean
@Conditional({ShardingRuleCondition.class})
public DataSource shardingDataSource() throws SQLException {
    return ShardingDataSourceFactory.createDataSource(this.dataSourceMap, (new ShardingRuleConfigurationYamlSwapper()).swap(this.shardingRule), this.props.getProps());
}

这里可以看到它已经为我们创建了一个叫shardingDataSource的Bean,所以我们要使用它给我们配置的DataSource。

这样,因为少了原来dataSource的配置,我们就需要去掉SpringBoot的数据源自动配置,否则,你会收到意外的惊喜,你也可以试试。
为了避免不必要的麻烦,我们需要在SpringBoot启动类上增加注解,排除掉Springboot的自动数据源配置。
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
或者在yml文件中增加如下配置:

spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

同时还要引入shardingsphere的自动配置:
@Import(value = {SpringBootConfiguration.class})

这里如果你忘记了手动引入,对不起,你会看到下面的Error:

org.springframework.jdbc.BadSqlGrammarException: ## Error querying database. Cause: org.h2.jdbc.JdbcSQLException: Table "T_USER" not found; SQL statement:
SELECT user_account AS userAccount, user_name AS userName, status, mobile FROM t_user [42102-197]

啥意思?没找到数据库表,因为在org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration类上还有一个注解:@AutoConfigureBefore({DataSourceAutoConfiguration.class})
而这个自动配置,在上边已经被我们给排除掉了。
因此,当我们干掉SpringBoot自动配置DataSource的时候,就需要手动的引入Sharding-Jdbc的自动配置了。

再次启动项目,如果你有测试类,试试insert或者update看看,数据其实已经华丽丽的变身了。

参考资料

  1. ShardingSphere数据加密

One thought on “使用Sharding-JDBC加密数据

  1. 原来的datasource跟 sharding-jdbc的datasource 不能共存吗?
    近期有springboot+mybatis项目有的表比较大, 需要引入sharding-jdbc,但是始终报文章中的错误

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注