SpringBoot 配置文件加密的步骤

作者:huifer 时间:2023-10-23 02:55:55 

目录
  • SpringBoot 配置文件加密

    • 编码

  • 其他

    SpringBoot 配置文件加密

    本章将对SpringBoot配置文件中的数据加密做自定义开发. 在SpringBoot开发过程中配置文件是明文存放在 application.yml 或者 application.properties 文件中,这种配置方式会带来一定的安全隐患,本章将对这个问题提出一个简单的解决方案。

    编码

    首先需要确定一个加密解密方式,本文采用 RSA 进行加密解密,首先编写加密解密的代码,注意RSA加密解密需要使用到公钥和私钥,公钥私钥的生成代码如下:


    public static void generateKey() throws NoSuchAlgorithmException {
     KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(EncryptionType.RSA);
     keyPairGen.initialize(1024, new SecureRandom());
     KeyPair keyPair = keyPairGen.generateKeyPair();
     RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();  // 得到私钥
     RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
     String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
     String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
     System.out.println("当前生成的公钥= " + publicKeyString);
     System.out.println("当前生成的私钥= " + privateKeyString);
    }

    加密代码如下:


    public static String encrypt(String str, String publicKey) throws NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException {
    byte[] decoded = Base64.decodeBase64(publicKey);
    RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(EncryptionType.RSA).generatePublic(new X509EncodedKeySpec(decoded));
    Cipher cipher = Cipher.getInstance(EncryptionType.RSA);
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
    }

    解密代码如下:


    public static String decrypt(String str, String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
     byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
     byte[] decoded = Base64.decodeBase64(privateKey);
     RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(EncryptionType.RSA).generatePrivate(new PKCS8EncodedKeySpec(decoded));
     Cipher cipher = Cipher.getInstance(EncryptionType.RSA);
     cipher.init(Cipher.DECRYPT_MODE, priKey);
     return new String(cipher.doFinal(inputByte));
    }

    上述代码为基本的加密解密工具,加下来需要在配置文件中确定哪些配置是需要进行解密的,本例将采用自定义前缀+后缀的方式进行匹配,前缀为 PWD[ ,后缀为 ] ,如果在配置文件中属性值是以前缀后缀包裹的那么这个数据会被进行解密操作,

    通过前文的加密工具可以先进行一次密码加密加密原文为 1234qwer ,公钥:


    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBOkkkvjbOQ6UTCo8U4bRC/EcEtxz8haHg6lueM3NBbH3eIT7kfwQFOqj1h1qPGcQNeyn4vxzMWBAKzSQehjqVBL7/8GN7EZ7TEaUuWO+8qsuZnOdrztX7bNKACnks+SelmtbrbnFKUMAq2c2mS0o1V6iwyRxJYLGaHGXnz4KSkwIDAQAB

    私钥:


    MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIE6SSS+Ns5DpRMKjxThtEL8RwS3HPyFoeDqW54zc0Fsfd4hPuR/BAU6qPWHWo8ZxA17Kfi/HMxYEArNJB6GOpUEvv/wY3sRntMRpS5Y77yqy5mc52vO1fts0oAKeSz5J6Wa1utucUpQwCrZzaZLSjVXqLDJHElgsZocZefPgpKTAgMBAAECgYAFaCDjTqoQWzgu4cQ2xXK7Ur7N7bNixVyOgn+u0MxDsnxZrN5qxP2wElI7Y5xgXF2diseoxqY3zn9tVEPsmwUcY73naoosx9V8oExgT/BUkZYIzj1ei08zOr984zl3dbFcxOCRvqywXj9FAAGx1mhmCzFCIauJg3aX0S9mt5/CwQJBAMYZsmMQ9owoXZuSclKVRfMHFpAPhQlcBM4xadhX0IRYATgNTxpESmcCoGWvyw3bvieNJyC9Njx6X4FJ2EZUzhECQQCm/2IM5MlsCwyKtME5RPFna2hSqYU80UzkNfDIyMokcU2JUI4Fhigog4ol0GFMiMBsHIjS+cJiAwNbIsq5rsJjAkA94yVBobkETFACHBwvBIdXxy0bUF3lcKPnrrQ8bCKuVbf7xNyjfhYoXD+zxNmQuMeNH6HLrpDVD/3qLCGuxyuhAkAiLPl/8gJWnhw+9qbkdXuB0rVS1WZy/9JgkblpHc5gjt9zTo0CDGaDhAftnSuMYiAe/+fwZTSmoj85k3ExdtZJAkEArJuG/NWY9HP4p7jtZX9rMokyB3517v7HQdJKBDIlOzseRC/roCvU8LQ/URDFBUqXCRgedxgW+0ZmKFf4xeawqw==

    加密结果为:


    PWD[bMw8oqC/ma31JqF0DCuf5QWqSFRMigYw3fMBIIIfJ85vnmNnFbH9IcJfUHgbSmNHeITffToODwAygy4vKdzu6o1i1UQOd8w4nPKhnVJCLKqW5jmc3Yw+FkTIRBp63NJWzECVnRHqEK+bTxPMa1gfKql/2U45XxqeDSZOEXGeA+E=]

    得到这个数据后将其配置在 application.properties 文件中,具体内容如下


    server.port=8080
    spring.application.name=test-app
    spring.datasource.password=PWD[bMw8oqC/ma31JqF0DCuf5QWqSFRMigYw3fMBIIIfJ85vnmNnFbH9IcJfUHgbSmNHeITffToODwAygy4vKdzu6o1i1UQOd8w4nPKhnVJCLKqW5jmc3Yw+FkTIRBp63NJWzECVnRHqEK+bTxPMa1gfKql/2U45XxqeDSZOEXGeA+E=]

    接下来需要进一步解决的是如何将这个加密字符串进行解密,这里需要使用 BeanFactoryPostProcessor 接口对环境变量进行修改,具体实现代码如下:


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    MutablePropertySources propertySources = environment.getPropertySources();

    for (PropertySource<?> propertySource : propertySources) {
      if (propertySource instanceof OriginTrackedMapPropertySource
      ) {
        OriginTrackedMapPropertySource om = (OriginTrackedMapPropertySource) propertySource;
        Map<String, Object> source = om.getSource();
        source.forEach((k, v) -> {
         String property = environment.getProperty(k);
         if (hasPreAndSuf(property)) {
           LOG.info("开始处理 k = [{}]", k);
           try {
            String relay = splitPreAndSuf(property, this.prefix, this.suffix);
            String decrypt = RSAEncrypt.decrypt(relay, getPrivateKey(environment));
            source.put(k, decrypt);
           }
           catch (Exception e) {
            LOG.error("e = ", e);
           }
         }
        });
      }
     }
    }

    处理逻辑如下:

    1. 提取环境配置中的所有配置属性

    2. 判断配置属性是否是 OriginTrackedMapPropertySource 类型,该类型的数据是在 application.yaml 中的内容

    3. 处理 OriginTrackedMapPropertySource 对象的value值,如果value包含自定义前缀后缀则进行解密

    在本例中对于公钥私钥以及前缀后缀是允许自定义的,开发者只需要在配置文件中根据下面表格进行填写即可

    属性名称属性含义默认值
    encryption.prefix前缀PWD[
    encryption.suffix后缀]
    encryption.rsa.publicKey公钥
    encryption.rsa.privateKey私钥

    注意:**为了便捷操作开放了配置文件形式的公钥秘钥的配置,这部分配置可以在测试环境中开发环境中进行使用。**如果需要在生产环境中使用请使用下面两种方式:

    方式一:在项目资源目录 resources 文件夹下创建 hf_private_key 文件,向文件中填写如下内容


    encryption.rsa.privateKey=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIE6SSS+Ns5DpRMKjxThtEL8RwS3HPyFoeDqW54zc0Fsfd4hPuR/BAU6qPWHWo8ZxA17Kfi/HMxYEArNJB6GOpUEvv/wY3sRntMRpS5Y77yqy5mc52vO1fts0oAKeSz5J6Wa1utucUpQwCrZzaZLSjVXqLDJHElgsZocZefPgpKTAgMBAAECgYAFaCDjTqoQWzgu4cQ2xXK7Ur7N7bNixVyOgn+u0MxDsnxZrN5qxP2wElI7Y5xgXF2diseoxqY3zn9tVEPsmwUcY73naoosx9V8oExgT/BUkZYIzj1ei08zOr984zl3dbFcxOCRvqywXj9FAAGx1mhmCzFCIauJg3aX0S9mt5/CwQJBAMYZsmMQ9owoXZuSclKVRfMHFpAPhQlcBM4xadhX0IRYATgNTxpESmcCoGWvyw3bvieNJyC9Njx6X4FJ2EZUzhECQQCm/2IM5MlsCwyKtME5RPFna2hSqYU80UzkNfDIyMokcU2JUI4Fhigog4ol0GFMiMBsHIjS+cJiAwNbIsq5rsJjAkA94yVBobkETFACHBwvBIdXxy0bUF3lcKPnrrQ8bCKuVbf7xNyjfhYoXD+zxNmQuMeNH6HLrpDVD/3qLCGuxyuhAkAiLPl/8gJWnhw+9qbkdXuB0rVS1WZy/9JgkblpHc5gjt9zTo0CDGaDhAftnSuMYiAe/+fwZTSmoj85k3ExdtZJAkEArJuG/NWY9HP4p7jtZX9rMokyB3517v7HQdJKBDIlOzseRC/roCvU8LQ/URDFBUqXCRgedxgW+0ZmKFf4xeawqw==

    需要将等于号后面的内容进行修改,替换为项目中的秘钥

    方式二:通过命令行进行传递

    在启动命令中添加


    -Dencryption.rsa.privateKey=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIE6SSS+Ns5DpRMKjxThtEL8RwS3HPyFoeDqW54zc0Fsfd4hPuR/BAU6qPWHWo8ZxA17Kfi/HMxYEArNJB6GOpUEvv/wY3sRntMRpS5Y77yqy5mc52vO1fts0oAKeSz5J6Wa1utucUpQwCrZzaZLSjVXqLDJHElgsZocZefPgpKTAgMBAAECgYAFaCDjTqoQWzgu4cQ2xXK7Ur7N7bNixVyOgn+u0MxDsnxZrN5qxP2wElI7Y5xgXF2diseoxqY3zn9tVEPsmwUcY73naoosx9V8oExgT/BUkZYIzj1ei08zOr984zl3dbFcxOCRvqywXj9FAAGx1mhmCzFCIauJg3aX0S9mt5/CwQJBAMYZsmMQ9owoXZuSclKVRfMHFpAPhQlcBM4xadhX0IRYATgNTxpESmcCoGWvyw3bvieNJyC9Njx6X4FJ2EZUzhECQQCm/2IM5MlsCwyKtME5RPFna2hSqYU80UzkNfDIyMokcU2JUI4Fhigog4ol0GFMiMBsHIjS+cJiAwNbIsq5rsJjAkA94yVBobkETFACHBwvBIdXxy0bUF3lcKPnrrQ8bCKuVbf7xNyjfhYoXD+zxNmQuMeNH6HLrpDVD/3qLCGuxyuhAkAiLPl/8gJWnhw+9qbkdXuB0rVS1WZy/9JgkblpHc5gjt9zTo0CDGaDhAftnSuMYiAe/+fwZTSmoj85k3ExdtZJAkEArJuG/NWY9HP4p7jtZX9rMokyB3517v7HQdJKBDIlOzseRC/roCvU8LQ/URDFBUqXCRgedxgW+0ZmKFf4xeawqw==

    需要将等号后面的内容进行修改,替换为项目中的秘钥

    从笔者所经历的角度来看命令行传递参数可能更加安全一些,因为文件和命令行相比命令行需要在生产环境才可以看到,而文件在仓库中会存在。

    接下来做一个测试,在启动时输出 spring.datasource.password 属性查看是否是加密前的数据,测试代码如下:


    @SpringBootApplication
    public class App {

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

    public static void main(String[] args) {
      SpringApplication.run(App.class, args);
     }

    @Bean
     public ApplicationRunner runner() {
      return args -> {
        System.out.println(dataSourceProperties);
      };
     }
    }

    启动项目后可以看到控制台输出


    1234qwer

    其他

    项目地址: https://gitee.com/pychfarm_admin/encryption

    来源:https://www.tuicool.com/articles/7jQramv

    标签:SpringBoot,文件,加密
    0
    投稿

    猜你喜欢

  • Matlab实现获取文件夹下所有指定后缀的文件

    2021-06-17 23:57:49
  • 深入讲解C#编程中嵌套类型和匿名类型的定义与使用

    2022-12-12 20:48:05
  • Nacos源码之注册中心的实现详解

    2023-04-30 19:25:49
  • Java Swing组件文件选择器JFileChooser简单用法示例

    2021-09-23 21:00:34
  • spring boot写java web和接口

    2022-10-02 09:52:02
  • java web学习_浅谈request对象中get和post的差异

    2022-10-28 00:25:20
  • idea的使用之关于tomcat热部署的教程

    2022-12-02 20:16:46
  • Jackson多态序列化图文详解

    2022-01-26 19:46:08
  • C#实现Socket通信的解决方法

    2022-06-01 22:06:00
  • Java版的7种单例模式写法示例

    2023-08-13 04:24:57
  • C#中实现Fluent Interface的三种方法

    2023-10-04 18:31:03
  • WinForm中Application.Idle方法详解

    2022-09-05 01:53:06
  • Android快速实现断点续传的方法

    2021-06-14 13:02:28
  • C# 循环判断会进来几次的实现代码

    2021-12-27 15:10:51
  • SpringBoot 多任务并行+线程池处理的实现

    2023-04-02 01:16:25
  • java实现简单的扫雷小游戏

    2022-09-14 19:23:24
  • C# WinForm实现自动更新程序的方法详解

    2021-12-12 16:19:54
  • javaweb Servlet开发总结(二)

    2023-10-31 11:51:48
  • 解决Java提示正在尝试分配更低的访问权限问题

    2023-11-04 09:31:08
  • docker网络配置过程详解介绍

    2023-02-07 23:04:15
  • asp之家 软件编程 m.aspxhome.com