>  기사  >  Java  >  springboot 프로젝트 데이터베이스 비밀번호를 암호화하는 방법

springboot 프로젝트 데이터베이스 비밀번호를 암호화하는 방법

WBOY
WBOY앞으로
2023-05-12 17:52:063818검색

옵션 1. druid 데이터베이스 연결 풀을 사용하여 데이터베이스 비밀번호를 암호화합니다

1. druid 패키지를 pom에 도입합니다. .filter.config.ConfigTools가 공개 키와 개인 키를 생성합니다

ps: 이를 생성하는 방법에는 두 가지가 있습니다. 명령줄을 사용하여 생성하는 방법과 도구 클래스를 직접 작성하여 생성하는 방법이 있습니다. 이 글의 예제에서는 도구 클래스를 직접 사용하여

도구 클래스 코드는 다음과 같습니다

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>${druid.version}</version>
  </dependency>

3. 데이터베이스 구성 파일 콘텐츠 정보

a를 수정하고, 비밀번호를 변경하세요
비밀번호를 생성된 비밀번호로 바꾸세요. DruidEncryptorUtils 도구 클래스

/**
 * alibaba druid加解密规则:
 * 明文密码+私钥(privateKey)加密=加密密码
 * 加密密码+公钥(publicKey)解密=明文密码
 */
public final class DruidEncryptorUtils {

    private static String privateKey;

    private static String publicKey;

    static {
        try {
            String[] keyPair = ConfigTools.genKeyPair(512);
            privateKey = keyPair[0];
            System.out.println(String.format("privateKey-->%s",privateKey));
            publicKey = keyPair[1];
            System.out.println(String.format("publicKey-->%s",publicKey));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        }
    }

    /**
     * 明文加密
     * @param plaintext
     * @return
     */
    @SneakyThrows
    public static String encode(String plaintext){
        System.out.println("明文字符串:" + plaintext);
        String ciphertext = ConfigTools.encrypt(privateKey,plaintext);
        System.out.println("加密后字符串:" + ciphertext);
        return ciphertext;
    }

    /**
     * 解密
     * @param ciphertext
     * @return
     */
    @SneakyThrows
    public static String decode(String ciphertext){
        System.out.println("加密字符串:" + ciphertext);
        String plaintext = ConfigTools.decrypt(publicKey,ciphertext);
        System.out.println("解密后的字符串:" + plaintext);

        return plaintext;
    }

b. 필터가 config


 password: ${DATASOURCE_PWD:HB5FmUeAI1U81YJrT/T6awImFg1/Az5o8imy765WkVJouOubC2H80jqmZrr8L9zWKuzS/8aGzuQ4YySAkhywnA==}

c를 열고, 연결 속성 속성

 filter:
                config:
                    enabled: true

ps을 구성합니다. spring.datasource.publickey는 도구 클래스에서 생성된 공개 키입니다


부록: 완료 데이터베이스 구성

 connection-properties: config.decrypt=true;config.decrypt.key=${spring.datasource.publickey}

옵션 2: jasypt를 사용하여 데이터베이스 비밀번호 암호화

1. jasypt 패키지를 pom에 도입합니다. a. ENC를 사용하여 JasyptEncryptorUtils

spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        url: ${DATASOURCE_URL:jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai}
        username: ${DATASOURCE_USERNAME:root}
        password: ${DATASOURCE_PWD:HB5FmUeAI1U81YJrT/T6awImFg1/Az5o8imy765WkVJouOubC2H80jqmZrr8L9zWKuzS/8aGzuQ4YySAkhywnA==}
        publickey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIvP9xF4RCM4oFiu47NZY15iqNOAB9K2Ml9fiTLa05CWaXK7uFwBImR7xltZM1frl6ahWAXJB6a/FSjtJkTZUJECAwEAAQ==
        druid:
            # 初始连接数
            initialSize: 5
            # 最小连接池数量
            minIdle: 10
            # 最大连接池数量
            maxActive: 20
            # 配置获取连接等待超时的时间
            maxWait: 60000
            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一个连接在池中最小生存的时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            # 配置一个连接在池中最大生存的时间,单位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # 配置检测连接是否有效
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            webStatFilter:
                enabled: true
            statViewServlet:
                enabled: true
                # 设置白名单,不填则允许所有访问
                allow:
                url-pattern: /druid/*
                # 控制台管理用户名和密码
                login-username:
                login-password:
            filter:
                stat:
                    enabled: true
                    # 慢SQL记录
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        multi-statement-allow: true
                config:
                    enabled: true
            connection-properties: config.decrypt=true;config.decrypt.key=${spring.datasource.publickey}

b에서 생성된 암호화된 문자열을 래핑합니다. 암호화 및 암호 해독 알고리즘

<dependency>
   <groupId>com.github.ulisesbocchio</groupId>
   <artifactId>jasypt-spring-boot-starter</artifactId>
   <version>${jasypt.verison}</version>
  </dependency>

내 도구 클래스는 암호화 및 암호 해독을 사용하므로 도구 클래스는 BasicTextEncryptor이고 해당 구성 암호화 및 암호 해독은 PBEWithMD5AndDES 및 org.jasypt.iv.NoIvGenerator

ps입니다. 프로덕션 환경에서 , 키 누출을 방지하려면 다음 방법으로 키를 구성하는 것이 좋습니다

public final class JasyptEncryptorUtils {


    private static final String salt = "lybgeek";

    private static BasicTextEncryptor basicTextEncryptor = new BasicTextEncryptor();

    static {
        basicTextEncryptor.setPassword(salt);
    }

    private JasyptEncryptorUtils(){}

    /**
     * 明文加密
     * @param plaintext
     * @return
     */
    public static String encode(String plaintext){
        System.out.println("明文字符串:" + plaintext);
        String ciphertext = basicTextEncryptor.encrypt(plaintext);
        System.out.println("加密后字符串:" + ciphertext);
        return ciphertext;
    }

    /**
     * 解密
     * @param ciphertext
     * @return
     */
    public static String decode(String ciphertext){
        System.out.println("加密字符串:" + ciphertext);
        ciphertext = "ENC(" + ciphertext + ")";
        if (PropertyValueEncryptionUtils.isEncryptedValue(ciphertext)){
            String plaintext = PropertyValueEncryptionUtils.decrypt(ciphertext,basicTextEncryptor);
            System.out.println("解密后的字符串:" + plaintext);
            return plaintext;
        }
        System.out.println("解密失败");
        return "";
    }
}

부록: 전체 데이터베이스 구성

password: ${DATASOURCE_PWD:ENC(P8m43qmzqN4c07DCTPey4Q==)}

옵션 3: 사용자 정의 구현


구현 원칙: 스프링 포스트 프로세서를 사용하여 데이터 소스 수정

1. 암호화 및 복호화 도구 클래스 맞춤화

jasypt:
    encryptor:
        password: lybgeek
        algorithm: PBEWithMD5AndDES
        iv-generator-classname: org.jasypt.iv.NoIvGenerator

2. 후처리기 쓰기

java -jar -Djasypt.encryptor.password=lybgeek

3. 데이터베이스의 구성 파일 내용 정보 수정

a, 비밀번호 수정
암호화된 비밀번호로 바꾸기 사용자 정의 암호화 도구 클래스

spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        url: ${DATASOURCE_URL:ENC(kT/gwazwzaFNEp7OCbsgCQN7PHRohaTKJNdGVgLsW2cH67zqBVEq7mN0BTIXAeF4/Fvv4l7myLFx0y6ap4umod7C2VWgyRU5UQtKmdwzQN3hxVxktIkrFPn9DM6+YahM0xP+ppO9HaWqA2ral0ejBCvmor3WScJNHCAhI9kHjYc=)}
        username: ${DATASOURCE_USERNAME:ENC(rEQLlqM5nphqnsuPj3MlJw==)}
        password: ${DATASOURCE_PWD:ENC(P8m43qmzqN4c07DCTPey4Q==)}
        druid:
            # 初始连接数
            initialSize: 5
            # 最小连接池数量
            minIdle: 10
            # 最大连接池数量
            maxActive: 20
            # 配置获取连接等待超时的时间
            maxWait: 60000
            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一个连接在池中最小生存的时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            # 配置一个连接在池中最大生存的时间,单位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # 配置检测连接是否有效
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            webStatFilter:
                enabled: true
            statViewServlet:
                enabled: true
                # 设置白名单,不填则允许所有访问
                allow:
                url-pattern: /druid/*
                # 控制台管理用户名和密码
                login-username:
                login-password:
            filter:
                stat:
                    enabled: true
                    # 慢SQL记录
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        multi-statement-allow: true
jasypt:
    encryptor:
        password: lybgeek
        algorithm: PBEWithMD5AndDES
        iv-generator-classname: org.jasypt.iv.NoIvGenerator

b에 의해 생성된 경우 키를 지정하고 암호화 기능을 활성화합니다

/**
 * 利用hutool封装的加解密工具,以AES对称加密算法为例
 */
public final class EncryptorUtils {

    private static String secretKey;



    static {
        secretKey = Hex.encodeHexString(SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded());
        System.out.println("secretKey-->" + secretKey);
        System.out.println("--------------------------------------------------------------------------------------");
    }

    /**
     * 明文加密
     * @param plaintext
     * @return
     */
    @SneakyThrows
    public static String encode(String plaintext){
        System.out.println("明文字符串:" + plaintext);
        byte[] key = Hex.decodeHex(secretKey.toCharArray());
        String ciphertext =  SecureUtil.aes(key).encryptHex(plaintext);
        System.out.println("加密后字符串:" + ciphertext);

        return ciphertext;
    }

    /**
     * 解密
     * @param ciphertext
     * @return
     */
    @SneakyThrows
    public static String decode(String ciphertext){
        System.out.println("加密字符串:" + ciphertext);
        byte[] key = Hex.decodeHex(secretKey.toCharArray());
        String plaintext = SecureUtil.aes(key).decryptStr(ciphertext);
        System.out.println("解密后的字符串:" + plaintext);

        return plaintext;
    }

    /**
     * 明文加密
     * @param plaintext
     * @return
     */
    @SneakyThrows
    public static String encode(String secretKey,String plaintext){
        System.out.println("明文字符串:" + plaintext);
        byte[] key = Hex.decodeHex(secretKey.toCharArray());
        String ciphertext =  SecureUtil.aes(key).encryptHex(plaintext);
        System.out.println("加密后字符串:" + ciphertext);

        return ciphertext;
    }

    /**
     * 解密
     * @param ciphertext
     * @return
     */
    @SneakyThrows
    public static String decode(String secretKey,String ciphertext){
        System.out.println("加密字符串:" + ciphertext);
        byte[] key = Hex.decodeHex(secretKey.toCharArray());
        String plaintext = SecureUtil.aes(key).decryptStr(ciphertext);
        System.out.println("解密后的字符串:" + plaintext);

        return plaintext;
    }
}

ps: 같은 이유로 구성 파일에 비밀 키를 직접 노출하지 않는 것이 가장 좋습니다. -Dcustom.encrypt.secret-key로 지정하세요

부록: 전체 데이터베이스 구성

public class DruidDataSourceEncyptBeanPostProcessor implements BeanPostProcessor {

    private CustomEncryptProperties customEncryptProperties;

    private DataSourceProperties dataSourceProperties;

    public DruidDataSourceEncyptBeanPostProcessor(CustomEncryptProperties customEncryptProperties, DataSourceProperties dataSourceProperties) {
        this.customEncryptProperties = customEncryptProperties;
        this.dataSourceProperties = dataSourceProperties;
    }



    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof DruidDataSource){
            if(customEncryptProperties.isEnabled()){
                DruidDataSource druidDataSource = (DruidDataSource)bean;
                System.out.println("--------------------------------------------------------------------------------------");
                String username = dataSourceProperties.getUsername();
                druidDataSource.setUsername(EncryptorUtils.decode(customEncryptProperties.getSecretKey(),username));
                System.out.println("--------------------------------------------------------------------------------------");
                String password = dataSourceProperties.getPassword();
                druidDataSource.setPassword(EncryptorUtils.decode(customEncryptProperties.getSecretKey(),password));
                System.out.println("--------------------------------------------------------------------------------------");
                String url = dataSourceProperties.getUrl();
                druidDataSource.setUrl(EncryptorUtils.decode(customEncryptProperties.getSecretKey(),url));
                System.out.println("--------------------------------------------------------------------------------------");
            }

        }
        return bean;
    }
}

위 내용은 springboot 프로젝트 데이터베이스 비밀번호를 암호화하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제