当前位置:   article > 正文

ShardingSphere(四)数据脱敏-实现自定义加密策略_shardingsphere aes解密

shardingsphere aes解密

ShardingSphere(四)数据脱敏-实现自定义加密策略

背景

目前官方文档脱敏部分给出的加密算法的配置都是基于内置的MD5和AES,有很多同学想要自定义加密算法并配置,但是不知道怎么做。可以参考以下实现过程及思路

注意

以下代码使用的ShardingSphere版本为4.1.1

关于数据脱敏详细的文档可参考官网数据脱敏部分

自定义加密策略一

实现Encryptor接口

这里采用SHA256的加密算法,由于SHA256加密是不可逆的。所以解密方法只返回密文

@Getter
@Setter
public final class Sha256Encryptor implements Encryptor {
    
    private Properties properties = new Properties();
    
    @Override
    public void init() {
        
    }
    
    @Override
    public String encrypt(final Object plaintext) {
        if (null == plaintext) {
            return null;
        }
        return DigestUtils.sha256Hex(String.valueOf(plaintext));
    }
    
    @Override
    public Object decrypt(final String ciphertext) {
        return ciphertext;
    }
    
    @Override
    public String getType() {
        return "SHA256";
    }
    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

在配置文件中配置(基于SpringBoot YAML)

这里对于要脱敏的字段进行配置,这里使用了两种加密策略,对于info字段采用默认的MD5加密,对于name字段采用自定义的SHA256加密

sharding:
  # 数据脱敏规则配置---start
      encrypt-rule:
          encryptors:
            encryptor_sha256:
              # 加密、解密器的名字,内置的为MD5,aes.
              # 可以自定义,实现
              # com.example.mybatis.demomybatis.shardingsphere.encrypt
              # 或者
              # org.apache.shardingsphere.encrypt.strategy.spi.QueryAssistedEncryptor
              # 这两个接口即可
              type: SHA256

            encryptor_MD5:
              type: md5
          tables:
            # 数据库,对应上面分片的tables
             user:
              columns:
                # 逻辑列,就是写SQL里面的列,因为实体类的名字和数据库的加密列一致,所以这里都是name
                name:
                  # 密文列,用来存储密文数据
                  cipherColumn: name
                  # 加密器名字
                  encryptor: encryptor_sha256
                other_info:
                  cipherColumn: info
                  encryptor: encryptor_MD5
      # 数据脱敏规则配置---end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

遇到的问题以及定位过程

配置完成之后,便去启动,此时启动报错,报错提示

Invalid `org.apache.shardingsphere.encrypt.strategy.spi.Encryptor` SPI type `SHA256`.
  • 1
  1. 根据错误找到了抛出异常的位置
    在这里插入图片描述

可以看到,是由于集合为空抛出的异常,那么这个集合是从哪来的?

  1. 进入loadTypeBasedServices(type)方法中,这个方法里只做了一件事,获取当前classtype的集合,并在集合中查找当前type(就是配置的SHA256)
    在这里插入图片描述
    可以看到,最终返回的集合里确实没有自定义的加密器,上面一行可以看到,result的最终结果都来自SERVICE_MAP中,那么说明自定义的加密策略并没有在这个map中
    在这里插入图片描述
    map里确实是没有

  2. 看来是在启动的时候没有把自定义的加密策略放到这个map里去造成的,通过debug对这个SERVICE_MAP进行watch发现,这个map是在
    在这里插入图片描述
    在register这里加入的,看到这里的注释就明白了,官方是通过SPI方式将各个功能通过插件的方式加入整个框架之中。这一点官方文档也有说。这里注册加密策略。可以看到,registerServiceClass这个方法往SERVICE_MAP中添加的元素。直接取决于ServiceLoader.load(srevice)这个方法

  3. 进入ServiceLoader.load

    该方法是java内置的spi机制

    顺着断点进去,看到reload好像也没发现什么,那就先看一下这个类是干嘛的,于是首先在注释中找到了答案
    在这里插入图片描述
    注释的前两段对servie-provider进行了详细的描述,关键在于第三部分,注释中明确指出了接入service-provider的说明。

    :在项目的resource目录下,新增配置文件,配置文件位于resource/META-INF/services下,配置文件的名字就是对外提供实现拓展服务的全路径名字,官方文档中加密策略对外提供的service的是Encryptor这个接口。配置文件里的内容就是实现了官方接口的类的全路径。于是看到这里,赶紧去配置一下

    后来发现,其实也没有好好看注释,在reload方法中注释表明了,最后会iterator,而最终的路径,以及路径里的内容也是在这里获得的
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    ServiceLoader是java.util包下的一个工具类,JDK8官方文档说明其他博主说明

在resource目录下新增配置

配置文件名字为:org.apache.shardingsphere.encrypt.strategy.spi.Encryptor
接口名字的完全限定名

配置文件里的内容,放入自定义的加密策略的类的全路径,和要使用官方内置的加密策略的类的全路径

com.example.mybatis.demomybatis.shardingsphere.encrypt.Sha256Encryptor
org.apache.shardingsphere.encrypt.strategy.impl.AESEncryptor
org.apache.shardingsphere.encrypt.strategy.impl.MD5Encryptor
com.example.mybatis.demomybatis.shardingsphere.encrypt.Sha256RandomEncryptor
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

验证自定义的加密策略是否生效

请求接口,通过debug自定义加密策略加解密方法、控制台打印SQL、数据库查看最终生成的数据、单元测试等手段验证了加密策略生效
在这里插入图片描述

解析

再回头看看ShardingSphere在配置了加密策略的时候,究竟干了什么

  1. ShardingSphere在生成数据源的时候会为数据源配置具体的ShardingRule

    方法详情见org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory#createDataSource

  2. 在ShardingRule中会根据配置生成对应的加密策略,以及配置加密策略对应的加密算法

    方法详情见org.apache.shardingsphere.core.rule.ShardingRule#createEncryptRule

  3. 具体读取配置文件,以及配置自定义的加密策略是在生成EncryptRule构造方法中的initEncryptors中

    方法详情见org.apache.shardingsphere.encrypt.rule.EncryptRule#initEncryptors

    这个方法的工作只有两步

    • 通过执行NewInstanceServiceLoader.register(Encryptor.class)静态代码块,注册配置的加密策略,通过读取固定位置下配置文件中的内容将具体的加密策略put进SERVICE_MAP中
    • 根据SERVICE_MAP中的加密策略,创建加密策略的实例,以便在进行数据库操作时根据配置选择对应的加密策略进行加密
  4. 在进行数据库操作时,根据配置的加密策略进行加密

自定义加密策略二

实现QueryAssistedEncryptor接口

至于QueryAssistedEncryptor的应用场景,请阅读官方文档数据脱敏部分

@Getter
@Setter
public final class Sha256RandomEncryptor implements QueryAssistedEncryptor {
    
    private Properties properties = new Properties();
    
    @Override
    public String queryAssistedEncrypt(final String plaintext) {
        if (null == plaintext) {
            return null;
        }
        // 原始字符串
        return DigestUtils.sha256Hex(String.valueOf(plaintext));
    }
    
    @Override
    public void init() {
    
    }
    
    @Override
    public String encrypt(final Object plaintext) {
        if (null == plaintext) {
            return null;
        }
        // 原始字符串+变动因子
        byte[] bytes = LocalDateTime.now().toString().getBytes();
        HMac hMac = new HMac(HmacAlgorithm.HmacSHA256, bytes);
        return hMac.digestHex(String.valueOf(plaintext));
    }
    
    @Override
    public Object decrypt(final String ciphertext) {
        return ciphertext;
    }
    
    @Override
    public String getType() {
        return "SHA256_RANDOM";
    }
    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

以当前时间戳作为变动因子,或者随机字符串也可以,对于密文列,采用HMac加密,对于查询辅助列,则使用普通的SHA256加密

数据表新增same_data子段

在配置文件中配置(基于SpringBoot YAML)

sharding:
  encrypt-rule:
          encryptors:
            encryptor_MD5:
              type: md5
            encryptor_sha256random:
              type: SHA256_RANDOM
          tables:
            # 数据库,对应上面分片的tables
             user:
              columns:
                # 逻辑列,就是写SQL里面的列,因为实体类的名字和数据库的加密列一致,所以这里都是name
                name:
                  # 密文列,用来存储密文数据
                  cipherColumn: name
                  # 加密器名字
                  encryptor: encryptor_sha256random
                  # 辅助查询列
                  assistedQueryColumn: same_data
                other_info:
                  cipherColumn: info
                  encryptor: encryptor_MD5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在配置文件中添加自定义的加密策略

在org.apache.shardingsphere.encrypt.strategy.spi.Encryptor文件中配置自定义加密策略

com.example.mybatis.demomybatis.shardingsphere.encrypt.Sha256Encryptor
org.apache.shardingsphere.encrypt.strategy.impl.AESEncryptor
org.apache.shardingsphere.encrypt.strategy.impl.MD5Encryptor
com.example.mybatis.demomybatis.shardingsphere.encrypt.Sha256RandomEncryptor
  • 1
  • 2
  • 3
  • 4

验证自定义加密策略是否生效

请求接口,通过debug自定义加密策略加解密方法、控制台打印SQL、数据库查看最终生成的数据、单元测试等手段验证了加密策略生效

  1. 可以看到数据库里的数据
    在这里插入图片描述
    对于name这个密文列,由于使用了自定义的加密策略,因为变动因子的原因,所以即使名字相同数据库里的存储也是不同的,而两条记录的same_data是一样的。对于没有变动因子的MD5加密策略,则info加密之后的存储信息也是一样的

  2. 通过name去数据库进行查询,即使密文列不相同,但是由于辅助查询列的存在,ShardingSphere能够准确的查出数据
    在这里插入图片描述

  3. 通过打印SQL发现,辅助查询列是新增数据的时候,ShardingSphere根据我们的加密策略以及配置的辅助查询的字段默认插入进去的,改写的SQL如下
    在这里插入图片描述
    ShardingSphere自动帮我们添加了辅助查询列

结束

以上示例代码已经放到GitHub上,如需,请自取。地址

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/756800
推荐阅读
相关标签
  

闽ICP备14008679号