一、前言

在我们日常开发过程中,由于业务的需要我们需要在数据库层面对某些关键性的信息进行加密存储,例如:身份证号、银行卡号、手机号、工资等信息进行加密存储,实现真正意义的数据混淆脱敏,以满足信息安全的需要,我们利用SpringBoot集成Sharding Sphere可以快速实现数据的加密解密功能。

二、Sharding Sphere介绍

在 Spring Boot 生态中,有一个非常厉害的开源框架:Apache ShardingSphere。

它是一款分布式 SQL 事务和查询引擎,可通过数据分片、弹性伸缩、加密等能力对任意数据库进行增强。我们可以利用它的数据脱敏模块,快速实现 SQL 字段的加解密操作。

三、项目实战

1.添加依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--shardingsphere数据分片、脱敏工具-->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-namespace</artifactId>
            <version>4.1.0</version>
        </dependency>

2.添加相关配置

#shardingsphere数据源集成
spring.shardingsphere.datasource.name=ds
spring.shardingsphere.datasource.ds.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds.jdbc-url=jdbc:mysql://127.0.0.1:3306/my_db?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.shardingsphere.datasource.ds.username=root
spring.shardingsphere.datasource.ds.password=123456

#加密方式、密钥配置
spring.shardingsphere.encrypt.encryptors.encryptor_aes.type=aes
spring.shardingsphere.encrypt.encryptors.encryptor_aes.props.aes.key.value=hkiqAXU6Ur5fixGHaO4Lb2V2ggausYwW
#plainColumn表示明文列,cipherColumn表示脱敏列
spring.shardingsphere.encrypt.tables.user.columns.phone.plainColumn=
spring.shardingsphere.encrypt.tables.user.columns.phone.cipherColumn=phone
#spring.shardingsphere.encrypt.tables.user.columns.pass_word.assistedQueryColumn=
spring.shardingsphere.encrypt.tables.user.columns.phone.encryptor=encryptor_aes

#sql打印
spring.shardingsphere.props.sql.show=true
spring.shardingsphere.props.query.with.cipher.column=true

#jpa配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.datasource.hikari.maximum-pool-size=100
spring.datasource.hikari.connection-timeout=8000

spring.shardingsphere.encrypt.tables是指要脱敏的表,user是表名,phone表示user表中的真实列,其中plainColumn指的是明文列,cipherColumn指的是脱敏列,如果是新工程,只需要配置脱敏列即可!

3.JPA相关配置

package com.example.dataproject.config;

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadata;
import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider;
import org.springframework.boot.jdbc.metadata.HikariDataSourcePoolMetadata;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author qx
 * @date 2024/8/7
 * @des
 */
@Configuration
public class JpaConfiguration {
    /**
     * 解决新版Spring中,健康健康检查用到 sharding jdbc 时,该组件没有完全实现MySQL驱动导致的问题.
     */
    @Bean
    DataSourcePoolMetadataProvider dataSourcePoolMetadataProvider() {
        return dataSource -> dataSource instanceof HikariDataSource                // 这里如果所使用的数据源没有对应的 DataSourcePoolMetadata 实现的话也可以全部使用 NotAvailableDataSourcePoolMetadata
                ? new HikariDataSourcePoolMetadata((HikariDataSource) dataSource)
                : new NotAvailableDataSourcePoolMetadata();
    }

    /**
     * 不可用的数据源池元数据.
     */
    private static class NotAvailableDataSourcePoolMetadata implements DataSourcePoolMetadata {
        @Override
        public Float getUsage() {
            return null;
        }

        @Override
        public Integer getActive() {
            return null;
        }

        @Override
        public Integer getMax() {
            return null;
        }

        @Override
        public Integer getMin() {
            return null;
        }

        @Override
        public String getValidationQuery() {
            // 该字符串是适用于MySQL的简单查询语句,用于检查检查,其他数据库可能需要更换
            return "select 1";
        }

        @Override
        public Boolean getDefaultAutoCommit() {
            return null;
        }
    }
}

4.创建数据实体

package com.example.dataproject.entity;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.*;

/**
 * @author qx
 * @date 2024/8/7
 * @des
 */
@Entity
@Table(name = "user")
@Getter
@Setter
@ToString
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private Integer age;

    private String phone;


}

5.创建数据持久层

package com.example.dataproject.dao;

import com.example.dataproject.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @author qx
 * @date 2024/8/7
 * @des 数据持久层
 */
public interface UserDao extends JpaRepository<User, Long> {
}

6.单元测试

package com.example.dataproject;

import com.example.dataproject.dao.UserDao;
import com.example.dataproject.entity.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class DataProjectApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void contextLoads() {
        //新增数据
        User user = new User();
        user.setName("admin");
        user.setAge(20);
        user.setPhone("18899998888");
        userDao.save(user);
    }

    @Test
    void query() {
        //查询数据
        List<User> userList = userDao.findAll();
        System.out.println(userList);
    }

}

我们先请求新增数据的测试方法,刷新数据表,发现我们成功新增了数据,并看到phone字段成功加密了。

SpringBoot集成Sharding Sphere实现数据加密解密_ShardingSphere

SpringBoot集成Sharding Sphere实现数据加密解密_加密_02

然后我们调用查询数据请求。数据被成功解密!结果如下图所示。

SpringBoot集成Sharding Sphere实现数据加密解密_加密_03

使用ShardingSphere 最大的好处就是直接通过配置脱敏列就可以完成对某些数据表字段的脱敏,非常方便。