java全家桶之42:JavaConfig=》db config加密解密

        本文介绍了基于Spring Boot的MySQL数据源配置实现。

        主要内容包括:

        1)通过application.yml配置MySQL连接参数,包括加密密码处理;

        2)定义MysqlDatasourceConfig类实现Druid数据源配置,包含连接池参数设置;

        3)主应用类Dbapi集成Eureka、Feign等服务;

        4)JavaConfig类处理配置解密和日志记录。

        该实现采用Druid连接池,支持加密密码自动解密,并提供了完善的连接池参数配置,适用于分布式微服务环境下的数据库连接管理。

本文详细介绍了基于SpringBoot和Druid的MySQL数据源配置方案。通过application.yml文件配置数据库连接参数,采用AES加密存储密码,配置类自动完成解密。核心实现包括:1)MysqlDatasourceConfig类配置Druid连接池参数;2)主应用Dbapi集成Eureka、Feign等微服务组件;3)JavaConfig类处理密码解密和日志记录。该方案支持连接池参数优化,如最大等待时间、初始连接数等配置,并提供了完善的MyBatis集成。加密模块采用Hutool工具实现AES加解密,确保敏感数据安全。整体架构适用于分布式微服务环境,兼顾安全性和性能。

配置:

spring:
  initializer:
    enabled: true
  batch:
    initializeSchema: always
    job:
      enabled: false

  datasource:
    mysql:
      enabled: true
      testWhileIdle: true
      driverClassName: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://${MYSQL_HOST:huawei.akunlong.top:13306}/platform?autoReconnect=true&autoReconnectForPools=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
      username: ${MYSQL_USER:root}
      password: ${MYSQL_PASSWORD:enc(LZXHOEwmmclHHip7QkVl3YQebNO4uNQJONS3usFEyMc=)}
      maxWait: 15000
      initialSize: 5
      minIdle: 2
      testOnBorrow: false
      validationQuery: SELECT 1

数据源定义

@Configuration
@Slf4j
@Data
@Primary
@ConditionalOnProperty(prefix = "spring.datasource.mysql", name = "enabled", havingValue = "true")
@MapperScan(basePackages = {"com.gitee.dbapi.data.dao.mysql"}, sqlSessionTemplateRef = "mysqlSessionTemplate")
public class MysqlDatasourceConfig extends DatasourceConfig {
    protected static String[] MYBATIS_MAPPER_LOCATIONS = new String[]{"classpath*:/mapper/mysql/*.xml"};
    protected static String MYBATIS_BASE_PACKAGE = "com.gitee.dbapi.data.dao.mysql";

    @Autowired
    JavaConfig javaConfig;
    @Qualifier("mysqlDataSource")
    @Bean("mysqlDataSource")
    //@ConfigurationProperties("spring.datasource.mysql")
    @Primary
    public DataSource mysqlDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setRemoveAbandoned(true);
        dataSource.setRemoveAbandonedTimeout(1800); // 30分钟
        dataSource.setLogAbandoned(true);
        DbConfigDto mysql = javaConfig.FindMysql();
        dataSource.setUsername(javaConfig.FindMysql().getUsername());
        dataSource.setPassword(javaConfig.FindMysql().getPassword());
        dataSource.setUrl(javaConfig.FindMysql().getUrl());
        dataSource.setDriverClassName(javaConfig.FindMysql().getDriverClassName());
        dataSource.setMaxWait(javaConfig.FindMysql().getMaxWait());
        dataSource.setInitialSize(mysql.getInitialSize());
        dataSource.setTestOnBorrow(false);
        dataSource.setValidationQuery(mysql.getValidationQuery());
        return dataSource;
    }

APP

@SpringBootApplication(scanBasePackages = {"com.gitee"},exclude={DruidDataSourceAutoConfigure.class, DataSourceAutoConfiguration.class})
@EnableEurekaClient
@EnableFeignClients(basePackages = "com.gitee.dbapi")
@EnableSwagger2
@EnableApolloConfig
@EnableDiscoveryClient
public class Dbapi {
     
    public static void main(String[] args) {        
        try {
            SpringApplication.run(Dbapi.class, args);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

java config

@Component
@Data
@ConfigurationProperties(prefix = "spring")
public class JavaConfig implements Serializable {
    private static final long serialVersionUID = 1L;
    @Autowired
    Map<String ,DbConfigDto> datasource;
    @PostConstruct
    public void decrypt() {

        FindMysql().setPassword(DbEncryptUtil.decrypt(FindMysql().getPassword()));
    }
public String Encrypt(String in) {

     return DbEncryptUtil.encrypt(in);
}
public DbConfigDto FindMysql(){
    return datasource.get("mysql");
}
@PostConstruct
public void logInfo() {
    log.info("========== 应用配置 ==========");
    log.info("javaConfig info:{}",this);
    log.info("=============================");
}

}

String r = DbEncryptUtil.encrypt("xxxxx@16xx3.comL");
@Data
@Component
public class DbConfigDto {
    boolean enabled;
    boolean testWhileIdle;//: true
    String driverClassName;//: oracle.jdbc.driver.OracleDriver
    String url;//: jdbc:oracle:thin:@192.168.4.111:1521:XE
    String username;//: leijmdas
    String password;//: leijmdas
    int maxWait;//: 15000
    int initialSize;//: 5
    int minIdle;//: 2
    boolean testOnBorrow;//: false
    String validationQuery;//: SELECT 1
}
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-extension</artifactId>
    <version>3.4.1</version>
</dependency>
package com.gitee.base.utils;

import org.apache.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.AES;
public class DbEncryptUtil {
    private static final String SECRET_KEY = "kunlong976823123";

    public static String encrypt(String data) {
            return AES.encrypt(data, SECRET_KEY);

    }

    public static String decrypt(String data) {
        if (IfEncypt(data)){
            data= StringUtils.remove(data,"enc(");
            data= StringUtils.remove(data,")");
            return AES.decrypt(data, SECRET_KEY);
        }
        return data;
    }

     public static boolean IfEncypt (String data) {
        return data.startsWith("enc(");
     }
 
}

Hutool提供了简洁强大的AES加密解密支持,以下是关键实现方法和注意事项:


🔑 一、基础加解密实现

  1. 添加依赖(Maven)

    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.20</version>
    </dependency>
    
  2. ECB模式加解密(默认模式,无需IV)

    // 加密(16进制结果)
    String encrypted = SecureUtil.aes(key.getBytes()).encryptHex(content);
    // 解密
    String decrypted = SecureUtil.aes(key.getBytes()).decryptStr(encrypted);
    

    :密钥需为 16/24/32字节(如1234567890123456)。

  3. Base64输出格式

    // 加密(Base64)
    String encryptBase64 = SecureUtil.aes(key.getBytes()).encryptBase64(content);
    // 解密
    String decryptStr = SecureUtil.aes(key.getBytes()).decryptStr(encryptBase64);
    

⚙️ 二、高级配置(CBC模式)

需指定初始化向量(IV)和填充方式:

// 密钥(16字节)和IV(16字节)
String key = "xxx", iv = "sdfsdf12345sfsdf";
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());

// 创建CBC模式AES对象
AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, keySpec, ivSpec);
// 加密
String encrypted = aes.encryptHex(content);
// 解密
String decrypted = aes.decryptStr(encrypted);

ECB vs CBC模式对比

特性ECB模式CBC模式
初始化向量不需要必须16字节
安全性较低(相同明文输出相同密文)更高(引入随机性)
适用场景简单加密需求敏感数据加密

⚠️ 三、关键注意事项

  1. 密钥管理

    • 禁止硬编码:密钥应存储于安全配置中心(如Vault)。

    • 长度校验:AES密钥需严格为16/24/32字节,否则报错Key length not 128/192/256 bits

  2. 编码一致性

    加解密时需统一字符编码(推荐UTF-8):

    String decrypted = aes.decryptStr(encrypted, CharsetUtil.CHARSET_UTF_8);
    
  3. 异常处理

    捕获CryptoException,避免密钥错误导致服务中断:

    try {
        String decrypted = aes.decryptStr(encrypted);
    } catch (CryptoException e) {
        log.error("解密失败: {}", e.getMessage());
    }
    

🔧 四、实用技巧

  1. URL参数加密

    加密后拼接URL:

    String param = "userId=114&tenantId=2";
    String encryptedParam = SecureUtil.aes(key.getBytes()).encryptHex(param);
    String url = "/api?data=" + URLEncoder.encode(encryptedParam);
    
  2. 密钥动态生成(仅测试环境)

    byte[] randomKey = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
    

💎 五、最佳实践建议

  • 算法选择:优先使用AES而非DES(DES已证实不安全)。

  • 模式推荐:敏感数据采用CBC+PKCS7填充或更安全的GCM模式。

  • 密钥轮转:定期更新密钥并兼容历史数据解密。

通过Hutool,仅需1-2行代码即可实现企业级AES加密,兼顾安全性与开发效率。建议结合具体业务需求选择模式,并严格遵循密钥安全管理规范。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leijmdas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值