文章目录
  1. 1. 引入依赖
  2. 2. 加密明文密码
  3. 3. 在程序中设置密文
  4. 4. 启动方法上配置自动加解密
  5. 5. 启动应用测试
  6. 6. 小结
  7. 7. 附录:命令行方式使用Jasypt加解密
    1. 7.1. 生成密文

生产上我们对数据库连接密码一般都是配置密文,从源头上尽可能地保证安全性。

本文中,我将介绍一款在Spring Boot中使用的自动加解密工具,对数据库连接密码进行加密操作。

该工具名为 jasypt-spring-boot-starter ,能够做到在Spring Boot 加载属性之前,对属性进行进行加解密操作。它使用对称加密方式进行加解密。

项目的Github为 jasypt-spring-boot, 感兴趣的可以去点个star支持下。

话不多说,进入正题。

引入依赖

还是基于我们的demo工程,首先在项目的pom.xml中引入maven依赖。

<!-- 集成数据库密码加密工具jasypt  jdk8版本-->
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>1.14</version>
</dependency>

加密明文密码

我们编写一个加密方法对密码明文进行加密操作。代码如下(需要依赖jasypt-spring-boot-starter包)

import org.jasypt.util.text.BasicTextEncryptor;

public class JasyptUtil {

    /**
    * 加密方法
    * @param salt 盐值
    * @param targetString 待加密字符串
    * @return 密文
    */
    public static String encrypt(String salt, String targetString) {
        BasicTextEncryptor encryptor = new BasicTextEncryptor();
        encryptor.setPassword(salt);
        return encryptor.encrypt(targetString);
    }

    /**
    * 解密方法
    * @param salt 盐值
    * @param targetString 待解密字符串
    * @return 明文
    */
    public static String decrypt(String salt,String targetString) {
        BasicTextEncryptor encryptor = new BasicTextEncryptor();
        encryptor.setPassword(salt);
        return encryptor.decrypt(targetString);
    }

    public static void main(String[] args) {
        String salt = "salt";
        String password = "test";
        // 进行加密操作
        String encryptString1 = encrypt(salt, password);
        // 进行解密操作
        String decryptString1 = decrypt(salt, encryptString1);
        // 输出明文和密文
        System.out.println("encryptString1="+encryptString1);
        System.out.println("decryptString1="+decryptString1);
    }
}

运行main方法,输出如下:

encryptString1=LIGKpRXjX0FD24N9E/kTsA==
decryptString1=root

解释一下,假设我们的数据库密码明文为:root,盐值为:salt,加密后的密文为:LIGKpRXjX0FD24N9E/kTsA==

在程序中设置密文

上一步中我们得到了连接数据库的密码密文,打开我们应用的配置文件application.properties,修改数据库连接密码为如下格式:

sharding.jdbc.datasource.ds0.password=ENC(LIGKpRXjX0FD24N9E/kTsA==)

通过 ENC(密文) 的方式,在程序中获取到的sharding.jdbc.datasource.ds0.password会自动转换成明文内容(root)。

由于我们加密的时候设置了加密的盐值,因此需要在application.properties中添加盐值,用于解密

#加密盐值
jasypt.encryptor.password=salt

启动方法上配置自动加解密

最后我们还需要在main方法上添加注解开启自动加解密,代码如下

@SpringBootApplication
@MapperScan(basePackages = "com.snowalker.shardingjdbc.snowalker.demo.mapper")
@EnableEncryptableProperties
public class SnowalkerShardingjdbcDemoApplication {

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

}

注解 @EnableEncryptableProperties 即是开启自动加解密的关键。

启动应用测试

运行main方法,看到日志如下,表示配置生效~

2019-03-14 14:05:44.853  INFO 25252 --- [           main] c.u.j.encryptor.DefaultLazyEncryptor     : Encryptor config not found for property jasypt.encryptor.stringOutputType, using default value: base64
2019-03-14 14:05:46.429  INFO 25252 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
2019-03-14 14:05:46.552  INFO 25252 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-2} inited
2019-03-14 14:05:46.693  INFO 25252 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-3} inited
2019-03-14 14:05:46.818  INFO 25252 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-4} inited
2019-03-14 14:05:47.196  INFO 25252 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-03-14 14:05:48.865  INFO 25252 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8091 (http) with context path ''
2019-03-14 14:05:48.868  INFO 25252 --- [           main] s.d.SnowalkerShardingjdbcDemoApplication : Started SnowalkerShardingjdbcDemoApplication in 6.374 seconds (JVM running for 8.048)

生产环境我们一般使用docker进行应用的部署,因此需要将数据库密码配置为环境变量,只需要修改配置文件application.properties中的密码配置如下:

# 通过ENC(密文)开启密码解密,不使用加密算法时,直接输入原始密码
sharding.jdbc.datasource.ds0.password=${mysql_db_password}

在docker容器启动时候通过-e配置环境变量,我们线上使用了Kubernates管理docker集群,只需要在helm部署文件的valus.yaml中配置环境变量。原理其实是相同的。

docker启动时配置方式如下:

docker run -d -v /log/snowalker/:/log --name sharding-jdbc-demo \
           -m 4g \
           -p 8081:8081 \
           -e db00_url="jdbc:mysql://127.0.0.1:3306/db_00?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8" \
           -e db01_url="jdbc:mysql://127.0.0.1:3306/db_01?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8" \
           -e db02_url="jdbc:mysql://127.0.0.1:3306/db_02?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8" \
           -e db03_url="jdbc:mysql://127.0.0.1:3306/db_03?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8" \
           -e db_username=root \
           -e db_password="ENC(LIGKpRXjX0FD24N9E/kTsA==)" \
           镜像仓库域名:5000/命名空间/sharding-jdbc-demo:1.0.1

核心配置为

-e db_password="ENC(LIGKpRXjX0FD24N9E/kTsA==)" \

注意添加双引号,否则会报错。

如果使用kubernates的helm方式部署,那么只需要在values.yaml中配置密码环境变量如下:

secret:
# 注意key不要使用减号'-'连接单词,如果需要一定使用下划线'_'
# 因为模板会识别key名称,自动并将key对应的值映射到容器中与key名称相同的环境变量上,而环境变量名称不支持减号'-'
# mysql
db00_url: 'jdbc:mysql://127.0.0.1:3306/db_00?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8'
db01_url: 'jdbc:mysql://127.0.0.1:3306/db_01?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8'
db02_url: 'jdbc:mysql://127.0.0.1:3306/db_02?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8'
db03_url: 'jdbc:mysql://127.0.0.1:3306/db_03?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8'
mysql_db_username: 'root'
mysql_db_password: 'ENC(LIGKpRXjX0FD24N9E/kTsA==)'

一定要将整个解密表达式设置到环境变量,如果appliation.properties中密码环境变量设置为如下方式则会报错

错误的配置!

sharding.jdbc.datasource.ds0.password=ENC(${mysql_db_password})

这种配置方式下,‘${mysql_db_password}’不会被识别为环境变量,而是普通的密码字符串,从而报错。

小结

到这里,我们就将数据库连接密码从明文设置为密文,我还在文章后半段讲解了如何通过环境变量设置密文到程序中。这里涉及到分布式开发下的“应用无状态”概念,在后续的文章中我会详细讲解如何开发无状态的应用。

接下来的文章中,我将继续带领读者对Sharding-JDBC进行深入的学习,Keep Moving。

附录:命令行方式使用Jasypt加解密

这里再介绍一种命令行下利用Jasypt加解密的方式。

生成密文

首先通过jasypt jar包生成密文:

D:\repository\org\jasypt\jasypt\1.9.2>
java -cp D:\repository\org\jasypt\jasypt\1.9.2\jasypt-1.9.2.jar
 org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="root"  
 password=salt algorithm=PBEWithMD5AndDES

jasypt需要设置用于加密明文的密钥password,它会对input内容加密。解释下参数:

参数 解释
input 密码原文
password 加密的盐值
algorithm 加密策略,对称加密

命令行下执行该命令,打印如下

----ENVIRONMENT-----------------

Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 25.181-b13

----ARGUMENTS-------------------

algorithm: PBEWithMD5AndDES
input: root
password: salt

----OUTPUT----------------------
guEfhaqV1d6LTCfhqsk6pQ==

OUTPUT打印的部分就是加密后的密文。

除了通过application.properties方式配置加密的盐值,我们还可以通过启动参数设置该参数,命令如下:

java -jar sharding-jdbc-demo.jar --jasypt.encryptor.password=salt
文章目录
  1. 1. 引入依赖
  2. 2. 加密明文密码
  3. 3. 在程序中设置密文
  4. 4. 启动方法上配置自动加解密
  5. 5. 启动应用测试
  6. 6. 小结
  7. 7. 附录:命令行方式使用Jasypt加解密
    1. 7.1. 生成密文
Fork me on GitHub