Springboot 之 配置文件属性加密


使用Jasypt对springboot项目的配置属性加密。
简书地址

写这篇的目的不是为了创新,而是备忘,最近学习clojure,java基本上已经放下了,但是曾今用过的东西如果不记录一下,以后用起来估计连查什么关键字都不知道了,因此在主页上做个笔记。

原来我们写的springboot的配置文件大概是这样的

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&useSSL=false
    username: root
    password: 123456

怎么看也是赤裸裸的,大概你也想过要是能加密就好了,如果只是想想的话,肯定不会自己加密,这里就介绍个非常方便易用的加密工具jasypt。

常规使用

在springboot中引入依赖

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

修改后的配置文件

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&zeroDateTimeBehavior=convertToNull&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&tinyInt1isBit=false
    # 对应用户名 root ,密码 123456
    username: ENC[KHRM9dKY8KykzzYbt8rRZQ==]
    password: ENC[RWmQMxlcukotJAb36PrKSA==]

jasypt:
  encryptor:
    # 任意的随机字符串均可
    password: SBPstLlrFzXW01Okb62R95qvpj4J83Dn
    property:
      # 自定义属性规则,默认前缀是“ENC(”,后缀为“)”
      prefix: "ENC["
      suffix: "]"

这里只加密了用户名和密码,其实所有属性,报过jdbc的url也是可以用同样的方式加密的。
留意到上面这段配置的用户名和密码是 ENC[xxx] 这种格式的,其中 ENC[] 是自定义配置的,这也是 Jasypt 能正常识别待解密数据的规则,那其中的加密串又是从哪来的呢?
当然是运算出来的。最简单的配置,开发者只需要再补充完 jasypt.encryptor.password=xxx 属性即可(同上,还支持使用 DER、PEM 这种证书的 private/public keys 加解密方式),具体的生成代码在下方:

@Slf4j
@SpringBootApplication
@EnableEncryptableProperties
public class JasyptSpringBootApplication &#123;

    public static void main(String[] args) &#123;
        ConfigurableApplicationContext context =
                SpringApplication.run(JasyptSpringBootApplication.class, args);
        JasyptSpringBootApplication application = context.getBean(JasyptSpringBootApplication.class);
        // 这里可以将明文(用户名、密码)转换成相应密文
        application.jasypt("root");
        application.jasypt("123456");

        // 不过程序最后还是通过明文信息进行数据库连接
        HikariDataSource hikariDataSource = (HikariDataSource) context.getBean(DataSource.class);
        log.info("DB username: &#123;&#125; , password: &#123;&#125;", hikariDataSource.getUsername(), hikariDataSource.getUsername());
    &#125;

    @Resource
    private StringEncryptor stringEncryptor;

    public void jasypt(String text) &#123;
        // 即使是相同明文,但这里每次生成的都是不同的密文
        String encryptedText = stringEncryptor.encrypt(text.trim());
        String decryptedText = stringEncryptor.decrypt(encryptedText);
        log.info("ORIGINAL: &#123;&#125; ; ENCRYPTED: &#123;&#125; ; DECRYPTED: &#123;&#125;", text, encryptedText, decryptedText);
    &#125;

&#125;

在开发环境要切换jdbc,或者看看密码到底是啥,为啥报jdbc链接错误时,可以用这个

import lombok.extern.slf4j.Slf4j;
import org.jasypt.encryption.StringEncryptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MobileOfficeApplication.class)
@Slf4j
public class MobileOfficeApplicationTests &#123;
    //@Test
    public void te()&#123;
        System.out.println(userService.encodePwd());
    &#125;

    @Autowired
    private StringEncryptor stringEncryptor;

    @Test
    public void contextLoads() &#123;
    &#125;

    @Test
    public void testEncrypt() &#123;
        System.out.println("=====================================");
        System.out.println("key1:" + stringEncryptor.encrypt("jdbc:p6spy:mysql://127.0.0.1:3306/chuangke?characterEncoding=utf-8&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Hongkong&autoReconnect=true\n"));
        System.out.println("key2:" + stringEncryptor.encrypt("root"));
        System.out.println("key3:" + stringEncryptor.encrypt("root"));
        System.out.println("=====================================");
    &#125;

&#125;

进阶

上面的例子是将password设置在与密文一起的配置文件中,这样方便是方便,但是有密码,有密文,知道加密算法,谁也可以解密呀(安全是相对的,其实这个已经很不错了),那有么有更安全的方式呢?
当然有!!!!
有两种办法:

  • 部署时设置password
    为了防止salt(盐)泄露,反解出密码.可以在项目部署的时候使用命令传入salt(盐)值
java -jar -Djasypt.encryptor.password=G0CvDz7oJn6 xxx.jar
  • 将password配置到服务器的环境变量里
# 打开/etc/profile文件
vim /etc/profile

#文件末尾插入
export JASYPT_PASSWORD = G0CvDz7oJn6

#编译 
source /etc/profile

#运行 
java -jar -Djasypt.encryptor.password=${JASYPT_PASSWORD} xxx.jar

参考

还将密码明文写在配置文件?试试 Jasypt Spring Boot


评论
  目录