不能直接用 ENC() 包裹 Oracle 密码,因为 Oracle 驱动在 DataSource 初始化前会严格校验 password 是否为合法字符串,若 jasypt 解密失败则抛 IllegalArgumentException 等异常;需手动解密后转为 char[] 传入。
为什么不能直接用 ENC() 包裹 Oracle 密码
spring boot 启动时,jasypt-spring-boot-starter 会自动扫描所有配置项,对形如 enc(xxx) 的值尝试解密。但 oracle 驱动(尤其是 ojdbc8)在初始化 datasource 前,会先校验 password 字段是否为合法字符串类型 —— 它不关心你是不是加密了,只认原始 string 值。一旦 jasypt 解密失败(比如密钥没传、算法不匹配、密文损坏),就会抛出 java.lang.illegalargumentexception: password is null 或更隐蔽的 pbestringdecryptioncli 类找不到等错误,而不是优雅 fallback。
char-decrypt 不是 Jasypt 内置逻辑,得自己写
Jasypt 没有叫 char-decrypt 的函数或配置项,这是常见误解。实际要实现的是:在 DataSource 构建前,把密文字符串手动解密成明文 char[] 或 String,再喂给连接池。Oracle 官方推荐密码用 char[] 传入(防内存 dump),所以“decrypt to char”本质是解密后转成 char[]。
- 不要依赖
@EnableEncryptableProperties自动解密spring.datasource.password—— 它只解密到String,且时机不可控 - 必须绕过 Spring Boot 自动装配,手写
@Bean构造DataSource - 解密逻辑要封装在构造函数或
@PostConstruct中,确保早于连接池初始化
手写 Oracle DataSource + 解密逻辑的关键三步
以 Druid 为例(兼容 Oracle,支持 setPassword() 接收 char[]),核心代码结构如下:
@Configuration
public class OracleDataSourceConfig {
@Value("${oracle.datasource.encrypted-password}")
private String encryptedPassword; // yml 里配 ENC(xxx),但不交给 spring boot 自动解
@Value("${jasypt.encryptor.password}")
private String jasyptKey;
@Bean
public DataSource dataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setUrl("${oracle.datasource.url}");
ds.setUsername("${oracle.datasource.username}");
// 关键:手动解密并转 char[]
String plainText = decrypt(encryptedPassword, jasyptKey);
ds.setPassword(plainText.toCharArray()); // ← 这才是真正的 "char-decrypt"
ds.setDriverClassName("oracle.jdbc.OracleDriver");
return ds;
}
private String decrypt(String cipher, String key) {
BasicTextEncryptor encryptor = new BasicTextEncryptor();
encryptor.setPassword(key);
// 注意:cipher 是纯密文,不含 ENC()
return encryptor.decrypt(cipher);
}
}
-
application.yml中不要写spring.datasource.password: ENC(...),改用自定义 key:oracle.datasource.encrypted-password: x7fFi8LBDyu4/FSEE8AYUg== - 密钥
jasypt.encryptor.password必须通过 JVM 参数(-Djasypt.encryptor.password=xxx)或环境变量注入,禁止硬编码在 yml 里 - 如果用 HikariCP,它只接受
String密码,那就用plainText而非toCharArray();Druid 才真正支持char[]
容易被忽略的 Oracle 兼容细节
Oracle 对密码长度、特殊字符、字符集敏感,解密后若含不可见字符(如 BOM、\u0000)或 UTF-8 乱码,连接会直接报 ORA-01017: invalid username/password,而非解密异常。
- 加密时确保输入是标准 ASCII 字符串,避免本地 IDE 编码(如 GBK)污染明文
- 解密后调用
plainText.trim().replaceAll("\u0000", "")清理零字节 - Oracle 12c+ 默认要求密码区分大小写,解密后大小写必须与数据库中完全一致
- 如果用
PBEWithMD5AndDES算法,JDK 8u161+ 已默认禁用,需降级 JDK 或换PBEWITHHMACSHA512ANDAES_256(需安装 JCE)
真正卡住人的从来不是“怎么加”,而是“解出来是不是 Oracle 认的那个字符串” —— 多打一行 System.out.println("[" + plainText + "]");,比查十篇文档都管用。


















