Redis密码在springboot中自定义加解密实践

在 Spring Boot 中为 Redis 密码实现自定义加解密,核心思路是:​配置文件中存储加密后的密码 → 启动时通过自定义 Bean 解密 → 将解密后的明文设置到 RedisConnectionFactory。以下是完整实践方案,包含加密工具、配置、Bean 定义及安全注意事项。

图片[1]_Redis密码在springboot中自定义加解密实践_知途无界

一、整体流程

  1. 加密原始密码​:使用自定义加密算法(如 AES、Base64 增强版等)对 Redis 原始密码加密,存储到 application.yml
  2. 自定义解密逻辑​:在 Spring Boot 启动时,通过 @Configuration 类读取加密密码,调用解密工具还原明文。
  3. 注入 Redis 连接池​:将解密后的明文设置到 RedisStandaloneConfigurationLettuceConnectionFactory,完成 Redis 连接。

二、步骤 1:定义加密/解密工具类

选择一个安全的加密算法(避免使用 Base64 等“伪加密”),这里以 ​AES 对称加密为例(需妥善保管密钥)。

1.1 AES 加密工具类(需引入 commons-codec 依赖)

<!-- pom.xml 依赖 -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.16.1</version>
</dependency>
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * AES 加密工具类(密钥需 16/24/32 字节,对应 AES-128/AES-192/AES-256)
 */
public class AESUtils {
    // 密钥(生产环境需存储在安全位置,如环境变量、配置中心,避免硬编码)
    private static final String SECRET_KEY = "MySecretKey123456"; // 16字节(AES-128)
    private static final String ALGORITHM = "AES/ECB/PKCS5Padding"; // 算法模式

    /**
     * AES 加密
     */
    public static String encrypt(String plainText) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "AES");
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.encodeBase64String(encryptedBytes); // 转为 Base64 字符串存储
    }

    /**
     * AES 解密
     */
    public static String decrypt(String encryptedText) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "AES");
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] decodedBytes = Base64.decodeBase64(encryptedText);
        byte[] decryptedBytes = cipher.doFinal(decodedBytes);
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }
}

1.2 生成加密后的密码(测试用)

public class TestEncrypt {
    public static void main(String[] args) throws Exception {
        String rawPassword = "my_redis_password_123"; // 原始密码
        String encryptedPassword = AESUtils.encrypt(rawPassword);
        System.out.println("加密后的密码:" + encryptedPassword); 
        // 输出示例:加密后的密码:U2FsdGVkX1+abc123...(实际为 Base64 字符串)
    }
}

将输出的加密字符串(如 U2FsdGVkX1+abc123...)存入配置文件。

三、步骤 2:Spring Boot 配置与解密 Bean

2.1 配置文件(application.yml

存储加密后的密码,避免明文暴露:

spring:
  redis:
    host: 192.168.1.100
    port: 6379
    # 存储加密后的密码(替换为实际加密结果)
    password: U2FsdGVkX1+abc123...  # 加密后的密码
    timeout: 2000ms
    lettuce:
      pool:
        max-active: 8
        max-wait: -1ms
        max-idle: 8
        min-idle: 0

2.2 自定义 Redis 配置类(核心)

通过 @Configuration 定义 RedisConnectionFactory,在初始化时解密密码并设置。

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import java.time.Duration;

@Configuration
public class RedisConfig {

    @Value("${spring.redis.host:localhost}")
    private String host;

    @Value("${spring.redis.port:6379}")
    private int port;

    @Value("${spring.redis.password:}") // 注入加密后的密码
    private String encryptedPassword;

    @Value("${spring.redis.timeout:2000ms}")
    private Duration timeout;

    @Value("${spring.redis.lettuce.pool.max-active:8}")
    private int maxActive;

    @Value("${spring.redis.lettuce.pool.max-idle:8}")
    private int maxIdle;

    @Value("${spring.redis.lettuce.pool.min-idle:0}")
    private int minIdle;

    @Value("${spring.redis.lettuce.pool.max-wait:-1ms}")
    private Duration maxWait;

    /**
     * 解密 Redis 密码并创建连接工厂
     */
    @Bean
    public LettuceConnectionFactory redisConnectionFactory() throws Exception {
        // 1. 解密密码(调用自定义解密工具)
        String rawPassword = AESUtils.decrypt(encryptedPassword); // 若解密失败会抛异常

        // 2. 配置 Redis 服务器信息
        RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration();
        serverConfig.setHostName(host);
        serverConfig.setPort(port);
        serverConfig.setPassword(RedisPassword.of(rawPassword)); // 设置解密后的明文密码

        // 3. 配置连接池(Lettuce)
        LettucePoolingClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
                .commandTimeout(timeout)
                .poolConfig(LettucePoolingClientConfiguration.builder()
                        .maxTotal(maxActive)
                        .maxIdle(maxIdle)
                        .minIdle(minIdle)
                        .maxWait(maxWait)
                        .build())
                .build();

        // 4. 创建并返回连接工厂
        return new LettuceConnectionFactory(serverConfig, clientConfig);
    }
}

2.3 验证 RedisTemplate 可用性

确保 RedisTemplate 能正常使用(Spring Boot 会自动注入 redisConnectionFactory):

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
public class TestController {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    public void testRedis() {
        redisTemplate.opsForValue().set("test:key", "hello_redis");
        String value = (String) redisTemplate.opsForValue().get("test:key");
        System.out.println("Redis 读取结果:" + value); // 输出 hello_redis
    }
}

四、关键注意事项

4.1 密钥安全管理

  • 禁止硬编码密钥​:示例中密钥写在代码里仅为演示,生产环境需将密钥存储在 ​环境变量配置中心(如 Nacos/Apollo)​​ 或 ​密钥管理服务(如 HashiCorp Vault)​
    示例(从环境变量读取密钥): private static final String SECRET_KEY = System.getenv("REDIS_AES_SECRET_KEY"); // 环境变量注入
  • 限制密钥访问权限​:确保密钥仅应用进程可读,避免泄露。

4.2 加密算法选择

  • 避免弱加密​:Base64 仅为编码(可逆且无安全性),不可用于密码保护;推荐使用 ​AES-256-GCM​(带认证)或 ​RSA​(非对称加密,适合分布式场景)。
  • 算法参数安全​:AES 的 ECB 模式不安全(相同明文生成相同密文),示例中使用 AES/ECB/PKCS5Padding 仅为简化,生产环境建议用 AES/GCM/NoPadding(需处理 IV 向量)。

4.3 异常处理

  • 解密失败处理​:若加密密码格式错误或密钥不匹配,AESUtils.decrypt() 会抛异常,需在 redisConnectionFactory() 中捕获并处理(如启动失败并提示配置错误)。 try { String rawPassword = AESUtils.decrypt(encryptedPassword); } catch (Exception e) { throw new IllegalStateException("Redis 密码解密失败,请检查配置", e); }
  • 配置文件校验​:启动时校验 spring.redis.password 是否为空或无效加密串,提前暴露问题。

4.4 其他方案对比

  • Spring Cloud Config + 加密​:若使用 Spring Cloud Config,可结合其内置的 {cipher}xxx 加密功能(基于 JCE),但需配置密钥服务器。
  • 第三方库​:如 jasypt-spring-boot,通过 @Encrypted 注解自动解密配置(需引入依赖并配置密钥),适合快速集成。

总结

通过 ​自定义加解密工具 + Spring Boot 配置类,可实现 Redis 密码的安全存储与动态解密。核心是隔离加密逻辑与业务代码,并通过安全的密钥管理保障解密过程的安全性。生产环境中需重点关注密钥管理和加密算法的强度,避免因配置不当导致密码泄露。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞87 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容