Spring Boot整合Jasypt增强应用安全

Jasypt是一个Java库,允许开发人员以很简单的方式添加基本加密功能,而无需深入研究加密原理。利用它可以实现高安全性的,基于标准的加密技术,无论是单向和双向加密。加密密码,文本,数字,二进制文件…

开发工具以及依赖版本信息

Maven 3.5.0
JDK 1.8.0
Spring Boot 2.1.1-RELEASE
jasypt-spring-boot-starter 2.0.0

整合步骤

一、加入依赖

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

二、 配置jasypt的加密密码

application.properties中配置加密需要使用的密钥。

jasypt.encryptor.password=EbfYk

三、加密内容

编写一个单元测试加密你需要加密的内容。

 @Autowired
    StringEncryptor jasyptStringEncryptor;
    @Test
    public void encrypt() {
        System.out.println("encrypt: " + jasyptStringEncryptor.encrypt("root"));
    }
    @Test
    public void decrypt() {
        System.out.println("decrypt: " + jasyptStringEncryptor.decrypt("o9uLVKcJV4C7SkdF9sZJzQ=="));
    }

四、修改配置信息

在application.properties中修改对应的参数信息

# 数据库基本配置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=Asia/Shanghai
spring.datasource.username=ENC(o9uLVKcJV4C7SkdF9sZJzQ==)
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

进一步增强安全性

通过上面的步骤,已经能在一定程度上保证安全性了,但是如果配置文件泄露就会造成加密密码的泄露,因此可以进行自定义加密的规则,即使不小心泄露配置文件,也可以保证安全性。
配置信息类 JasyptConfiguration .java

import org.jasypt.encryption.StringEncryptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import com.ulisesbocchio.jasyptspringboot.EncryptablePropertyDetector;

/**
* @author Jackieonway
* @version \$Id: JasyptConfiguration.java, v 0.1 2019-07-30 9:22 Jackieonway Exp $
*/
@Configuration
public class JasyptConfiguration {

   @Bean("jasyptStringEncryptor")
   public StringEncryptor stringEncryptor(Environment environment){
       return new MyJasyptStringEncryptor(environment);
   }
}

加解密类 JasyptStringEncryptor.java

import java.nio.charset.StandardCharsets;
import java.util.UUID;

import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.StandardPBEByteEncryptor;
import org.jasypt.encryption.pbe.config.PBEConfig;
import org.jasypt.encryption.pbe.config.SimplePBEConfig;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;

/**
 * @author Jackieonway
 * @version \$Id: JasyptStringEncryptor.java, v 0.1 2019-07-30 9:48 Jackieonway Exp $
 */
public class JasyptStringEncryptor implements StringEncryptor {

    private static final Logger log = LoggerFactory.getLogger(JasyptStringEncryptor.class);

    private final StandardPBEByteEncryptor byteEncryptor;
    private final Base64 base64;

    public JasyptStringEncryptor() {
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword("EdLKOREFDMI/sddnc@A");
        config.setAlgorithm("PBEWithMD5AndDES");
        this.byteEncryptor = new StandardPBEByteEncryptor();
        this.byteEncryptor.setConfig(config);
        this.base64 = new Base64();
    }

    public JasyptStringEncryptor(Environment environment) {
        byteEncryptor = new StandardPBEByteEncryptor();
        byteEncryptor.setConfig(getConfig(environment));
        this.base64 = new Base64();
    }

    public JasyptStringEncryptor(String password) {
        SimplePBEConfig config = new SimplePBEConfig();
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setPassword(password);
        byteEncryptor = new StandardPBEByteEncryptor();
        byteEncryptor.setConfig(config);
        this.base64 = new Base64();
    }

    public JasyptStringEncryptor(SimpleStringPBEConfig config) {
        byteEncryptor = new StandardPBEByteEncryptor();
        byteEncryptor.setConfig(config);
        this.base64 = new Base64();
    }

    @Override
    public String encrypt(String s) {
        byte[] encrypt = byteEncryptor.encrypt((s).getBytes());
        byte[] encode = base64.encode(encrypt);
        return new String(encode,StandardCharsets.UTF_8);
    }

    @Override
    public String decrypt(String s) {
        byte[] decode = base64.decode(s.getBytes());
        byte[] decrypt  = byteEncryptor.decrypt(decode);
        return new String(decrypt,StandardCharsets.UTF_8);
    }
    private PBEConfig getConfig(Environment e){
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(getRequiredProperty(e, "jasypt.encryptor.password"));
        config.setAlgorithm(getProperty(e, "jasypt.encryptor.algorithm", "PBEWithMD5AndDES"));
        config.setKeyObtentionIterations(getProperty(e, "jasypt.encryptor.keyObtentionIterations", "1000"));
        config.setPoolSize(getProperty(e, "jasypt.encryptor.poolSize", "1"));
        config.setProviderName(getProperty(e, "jasypt.encryptor.providerName", null));
        config.setSaltGeneratorClassName(getProperty(e, "jasypt.encryptor.saltGeneratorClassname", "org.jasypt.salt.RandomSaltGenerator"));
        config.setStringOutputType(getProperty(e, "jasypt.encryptor.stringOutputType", "base64"));
        return config;
    }

    private static String getProperty(Environment environment, String key, String defaultValue) {
        if (!propertyExists(environment, key)) {
            log.info("Encryptor config not found for property {}, using default value: {}", key, defaultValue);
        }
        return environment.getProperty(key, defaultValue);
    }

    private static boolean propertyExists(Environment environment, String key) {
        return environment.getProperty(key) != null;
    }

    private static String getRequiredProperty(Environment environment, String key) {
        if (!propertyExists(environment, key)) {
            throw new IllegalStateException(String.format("Required Encryption configuration property missing: %s", key));
        }
        return environment.getProperty(key);
    }

}

如果不想使用jasypt提供的前缀和后缀,使用下面的代码将原来的替换成您想要使用的任何前后缀

jasypt.encryptor.property.prefix=TEST(
jasypt.encryptor.property.suffix=)

觉得还是有可能因为加密密码造成泄漏,那么可以使用启动参数形式* --jasypt.encryptor.password=*

 java -jar xxx.jar --jasypt.encryptor.password=xxx

还可以使用环境变量的形式来获取加密密码

  #设置环境变量:

  # 打开/etc/profile文件

  vim /etc/profile

  # 文件末尾插入

  export JASYPT_PASSWORD = xxxx

  #启动命令:

  java -jar xxx.jar --jasypt.encryptor.password=${JASYPT_PASSWORD}

小结

经过上述一顿胡乱操作之后,Spring Boot整合Jasypt就成功啦,您的应用就可以更加安全的运行了


作者: jackieonway
原文:https://www.jianshu.com/p/838f4d2b926a