zoukankan      html  css  js  c++  java
  • Spring Boot: 加密应用配置文件敏感信息

    Spring Boot: 加密应用配置文件敏感信息

    背景

    1. 我们的应用之前使用的是Druid数据库连接池,由于需求我们迁移到HikariCP连接池,druid 数据源加密提供了多种方式:
    • 可以在配置文件my.properties中指定config.decrypt=true
    • 也可以在DruidDataSource的ConnectionProperties中指定config.decrypt=true
    • 也可以在jvm启动参数中指定-Ddruid.config.decrypt=true

    但是HikariCP 默认没有提供实现数据源加解密的方法

    1. 应用中会存在多个需要配置敏感信息(比如stfp等),都需要加密,类似于druid加解密方式依赖于工具类的实现,没有统一的加解密标准,麻烦、而且不好维护。

    case1:Spring Cloud Config 的解决方案

    1. Config Server 加解密依赖JDK的JCE。

    JDK8的下载地址

    1. 配置config serve encrypt.key=foo
    2. 使用config server 提供的加解密接口生成密文
    curl localhost:4001/encrypt -d lengleng
    密文
    1. 配置文件使用密文
    spring:
      datasource:
        password: '{ciper}密文'
    
    xxx: '{ciper}密文'    
        
    其他的非对称加密等高级配置,参考官方文档。注意一个bug (No key was installed for encryption service

    case2:jasypt 的解决方案

    一,首先引入Maven/Gradle 依赖

    Maven
    <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>1.14</version> </dependency>


    Gradle
    compile 'com.github.ulisesbocchio:jasypt-spring-boot-starter:1.14'
    2.1.0版本是我用的时候最新版本。查看最新版本可以到
    https://github.com/ulisesbocchio/jasypt-spring-boot 查看
     

    二,application.yml配置文件中增加如下内容(加解密时使用)

    #jasypt加密的密匙
    jasypt:
      encryptor:
        password: EbfYkitulv73I2p0mXI50JMXoaxZTKJ7

    三,在测试用例中生成加密后的秘钥:

    1. 创建我们一个工具包JasyptUtils
    package com.testPro;
    
    import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
    import org.jasypt.encryption.pbe.StandardPBEByteEncryptor;
    import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
    import org.junit.Test;
    
    public class JasyptUtils {
    
        /**
         * Jasypt生成加密结果
         *
         * @param password 配置文件中设定的加密密码 jasypt.encryptor.password
         * @param value    待加密值
         * @return
         */
        public static String encryptPwd(String password, String value) {
            PooledPBEStringEncryptor encryptOr = new PooledPBEStringEncryptor();
            encryptOr.setConfig(cryptOr(password));
            String result = encryptOr.encrypt(value);
            return result;
        }
    
        /**
         * 解密
         *
         * @param password 配置文件中设定的加密密码 jasypt.encryptor.password
         * @param value    待解密密文
         * @return
         */
        public static String decyptPwd(String password, String value) {
            PooledPBEStringEncryptor encryptOr = new PooledPBEStringEncryptor();
            encryptOr.setConfig(cryptOr(password));
            String result = encryptOr.decrypt(value);
            return result;
        }
    
        public static SimpleStringPBEConfig cryptOr(String password) {
            SimpleStringPBEConfig config = new SimpleStringPBEConfig();
            config.setPassword(password);
            config.setAlgorithm(StandardPBEByteEncryptor.DEFAULT_ALGORITHM);
            config.setKeyObtentionIterations("1000");
            config.setPoolSize("1");
            config.setProviderName("SunJCE");
            config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
            config.setStringOutputType("base64");
            return config;
        }
    
        @Test
        public void test() {
            String jasyptPassword = "123456";//盐值
            // 加密
            System.out.println("###encryptPwd:" + encryptPwd(jasyptPassword, "appserver123"));
            // 解密
            System.out.println("###decyptPwd:" + decyptPwd(jasyptPassword, "SaYJ7DkUlL3gxzt4zrNG4t0lGXzk9x9C"));
        }
    }

    四,将上面生成的name和password替换配置文件中的数据库账户和密码,替换后如下:

    --格式:
    spring:
    datasource:
    password: ENC(DBA提供的密文)

      注意上面的 ENC()是固定写法,()里面是加密后的信息。


    spring: #数据库相关配置 datasource: driver
    -class-name: com.mysql.jdbc.Driver #这里加上后缀用来防止mysql乱码,serverTimezone=GMT%2b8设置时区 url: ENC(i87lLC0ceVq1vK91R+Y6M9fAJQdU7jNp5MW+ndLgacRvPDj42HR8mUE33uFwpWqjOSuDX0d1dd2NilrnW7yJbZmoxuJ3HmOmjwY5+Vhu+e3We4QPDVCr/s/RHsQgYOiWrSQ92Mjammnody/jWI5aaw==) username: appserver password: ENC(SaYJ7DkUlL3gxzt4zrNG4t0lGXzk9x9C) #appserver123 jpa: hibernate: ddl-auto: update show-sql: true #返回的api接口的配置,全局有效 jackson: default-property-inclusion: non_null #如果某一个字段为null,就不再返回这个字段 #url相关配置,这里配置url的基本url server: port: 8888 #jasypt加密的密匙(盐值) jasypt: encryptor: password: 123456

    其他非对称等高级配置参考
    Key                                  Required    Default Value
    jasypt.encryptor.password            True        -
    jasypt.encryptor.algorithm            False    PBEWithMD5AndDES
    jasypt.encryptor.keyObtentionIterations    False    1000
    jasypt.encryptor.poolSize            False    1
    jasypt.encryptor.providerName          False    SunJCE
    jasypt.encryptor.saltGeneratorClassname    False    null
    jasypt.encryptor.saltGeneratorClassname    False    org.jasypt.salt.RandomSaltGenerator
    jasypt.encryptor.stringOutputType        False    base64
    jasypt.encryptor.proxyPropertySources      False    false
    
    

    总结

    1. Spring Cloud Config 提供了统一的加解密方式,方便使用,但是如果应用配置没有走配置中心,那么加解密过滤是无效的;依赖JCE 对于低版本spring cloud的兼容性不好。
    2. jasypt 功能更为强大,支持的加密方式更多,但是如果多个微服务,需要每个服务模块引入依赖配置,较为麻烦;但是功能强大 、灵活。
    3. 个人选择 jasypt
    4. 源码参考: 基于Spring Cloud、JWT 的微服务权限系统设计
    5. https://segmentfault.com/a/1190000012363841
    6. https://www.jianshu.com/p/b047ed4a8dfa
    7. https://zhiku8.com/springboot-jasypt.html
  • 相关阅读:
    go里面redis缓存池
    go语言操作redis
    goredis的操作
    go安装redis扩展
    go协程聊天室
    go里面os包的使用案例
    用php入门网络编程
    使用go里面实现了一个并发的时钟服务器
    案例一:协程创建和使用
    系统工程笔记
  • 原文地址:https://www.cnblogs.com/zt007/p/9675507.html
Copyright © 2011-2022 走看看