您现在的位置是:首页 >学无止境 >shardingjdbc-5.3.2加解密网站首页学无止境

shardingjdbc-5.3.2加解密

起风哥 2023-06-04 00:00:03
简介shardingjdbc-5.3.2加解密

上一篇文章`数据库敏感字段脱敏集成了shading-jdbc-core-4.0.1 后续的业务遇到了很多坑,于是决定升级,花了好大劲升级到了4.1.1,发现还是好多坑,于是又花了好大劲总算升级到了5.3.2,才摆脱这些坑,但是还是有一点小问题,不支持将加解密字段作为临时表的条件。

4.0.1 不支持sql的if语句,group by,子查询等语句,而4.1.1不支持别名的查询,查看官方的更新日志,发现别名查询的问题在5.3.1修复的。

不同版本的文档

虽然大版本间差异非常大,但是还是建议使用最新版,5.3.2版本需要依赖snackeyaml 版本1.33 不然会报找不到setPointLimit方法的错误。

springboot项目下我们可以使用两种方式进行集成一种是直接引用starter组件,第二种是自己手工集成,可以让配置更简单点

shardingshpere-jdbc 5.x版本包有点多,可以花点时间整理下它对应的包,看下哪些包是没有必要的可以移除掉。

使用starter方式集成

引入starter依赖

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.2.1</version>
</dependency>

然后可以根据官方文档直接配置即可

集成方式二:手工集成

引入依赖

<dependency>
                <groupId>org.apache.shardingsphere</groupId>
                <artifactId>shardingsphere-jdbc-core</artifactId>
                <version>5.3.2</version>
            </dependency>

编写配置类

@Configuration
public class EncryptDatasourceConfiguration {

    @Value("${spring.datasource.druid.driver-class-name}")
    String driverClassName;

    @Value("${spring.datasource.druid.username}")
    String username;

    @Value("${spring.datasource.druid.password}")
    String password;

    @Value("${spring.datasource.druid.url}")
    String url;

    @Autowired
    EncryptProperties encryptProperties;

    @Bean
    public DataSource dataSource() throws SQLException {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setJdbcUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        // 配置脱敏规则
        Properties props = new Properties();
        props.setProperty("aes-key-value", encryptProperties.getUser().getAesSecret());
        AlgorithmConfiguration encryptor = new AlgorithmConfiguration("AES", props);
        Map<String, AlgorithmConfiguration> encryptors=new HashMap<>();
        final String encryptorName="aes-encryptor";
        encryptors.put(encryptorName,encryptor);

        Map<String, List<String>> tableListMap = encryptProperties.getUser().getTableFields();
        Collection<EncryptTableRuleConfiguration> tables=new ArrayList<>();

        tableListMap.forEach((table, fields) -> {
           List<EncryptColumnRuleConfiguration> columns = Lists.newArrayList();
            fields.forEach(field -> {
                //字段配置
                EncryptColumnRuleConfiguration columnConfig = new EncryptColumnRuleConfiguration(field,
                        field, "","","" ,encryptorName,true);
                columns.add(columnConfig);
            });
            //表对应字段配置
            EncryptTableRuleConfiguration tableConfig = new EncryptTableRuleConfiguration(table,columns,true);
            tables.add(tableConfig);
        });
        // 配置脱敏规则
        EncryptRuleConfiguration config = new EncryptRuleConfiguration(tables,encryptors);
        // 获取数据源对象
        return ShardingSphereDataSourceFactory.createDataSource(dataSource, Arrays.asList(config), new Properties());
    }

}

配置类

@Configuration
@ConfigurationProperties(prefix = "encrypt")
@Data
public class EncryptProperties {
    private Encrypt user;
    @Data
    public static class Encrypt {
        //key=table , value=columns
        private Map<String, List<String>> tableFields;
        private String aesSecret;
    }
}

配置文件

encrypt:
  user:
    aesSecret: xxxxx
    tableFields:
      user_table:
        - user_column
        - phone_column
        - id_no_column
      other_table:
        - id_no_column
        - bank_card_column      

注意以上只是最简单的方式。

EncryptColumnRuleConfiguration 列的加解密规则解析

	//逻辑字段,这个相当于key 即哪个列需要加解密,必填
    private final String logicColumn;
    //加密列,这个配置跟逻辑列一样即可
    private final String cipherColumn;
    //辅助查询列
    private final String assistedQueryColumn;
    //like查询列
    private final String likeQueryColumn;
    //明文列
    private final String plainColumn;
    //加密器
    private final String encryptorName;
    //辅组查询算法加密器
    private final String assistedQueryEncryptorName;
    //like查询加密器
    private final String likeQueryEncryptorName;
    //是否查询加密列,这个设置为true就会查询加解密的列
    private final Boolean queryWithCipherColumn;

如果你也只是需要简单的加解密某个字段,只需要设置 logicColumn,cipherColumn、encryptorName三个属性即可

如果你需要做like查询之类的,可以参考官方的文档选择加密算法,然后设置like查询列,并设置加密算法。这个是真的牛b

两种数据整合的方案,一般全新的项目或数据你怎么搞都可以
但是一般我们的项目都是存在历史数据的,所以需要进行平滑过渡,这个也是很好实现的,比如phone这个字段需要进行加密,但是有历史数据,怎么办呢?
新增一个列phone_encrypt,将这个列设置为加密列,phone设置为明文列,并且关闭加密列查询。一段时间后,开启加密列查询,并且将phone_encrypt改为phone。目前不知道这种方案有啥优势。我们的做法是,直接写个工具类把数据库数据进行一遍清洗,然后直接上,最直接了当。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。