根本原因是jdbc驱动与oracle服务端密码哈希校验不匹配,涉及驱动版本过旧、连接串语法错误(如引号缺失、特殊字符未转义)、多租户下pdb路由错误及用户密码哈希段spare4为空。

为什么SQL*Plus能连,JDBC却报ORA-01017?
根本原因不是密码输错,而是JDBC驱动与服务端在密码哈希校验环节不匹配——SQL*Plus可能用兼容层绕过校验,而JDBC直传原始凭据,触发严格比对失败。
-
ojdbc8.jar连接 Oracle 19c/21c 时,因密码算法不支持(仅兼容到 12.2),会把正确密码当成无效值提交 - classpath 中混入多个
ojdbc版本(比如 Tomcatlib/下残留ojdbc6.jar),JVM 加载了旧驱动 - Oracle 19c 默认禁用旧式 DES 密码哈希,若用户密码是 11g 时代创建且未重置,
s:段哈希为空或不完整,JDBC 拒绝认证
检查JDBC连接串里的引号和特殊字符
Java 字符串解析 + Oracle 驱动双重处理,让引号缺失或错位直接导致凭据截断。
- 密码含
@、/、:、$时,必须用英文双引号包裹:Password="Pass@123",否则驱动在解析 URL 时提前截断 - 用户名含小写字母或下划线(如
my_user),也得加引号:User Id="my_user",否则 Oracle 内部转成大写MY_USER查无此人 - Spring Boot 的
application.yml中写连接串,要用单引号包裹整个值,避免 YAML 解析器吃掉反斜杠或冒号:url: 'jdbc:oracle:thin:@//host:1521/orclpdb1'
确认用户实际所在容器与连接串是否匹配
ORA-01017 在 12c+ 多租户环境下,常因连接路由到 CDB 根而非目标 PDB,导致“用户不存在”式认证失败。
- 连接串用 SID 格式(
@host:1521:ORCL)会强制走 CDB,但普通用户只存在于 PDB(如orclpdb1) - 必须用服务名格式:
@//host:1521/orclpdb1或完整 TNS 别名,且该别名的SERVICE_NAME明确指向 PDB - 查用户归属:
SELECT con_id, username FROM cdb_users WHERE username = 'MYUSER';返回CON_ID > 1即说明在某个 PDB 中
验证密码哈希是否支持JDBC直连
关键看 spare4 字段里有没有有效的 s: 哈希段——没有它,JDBC 就无法完成现代认证流程。
- 以 SYSDBA 登录后执行:
SELECT username, password_versions, spare4 FROM dba_users WHERE username = 'MYUSER' - 若
password_versions是10G 11G 12C,但spare4为空或只有t:段,说明密码未按新协议重置 - 强制刷新哈希:
ALTER USER myuser IDENTIFIED BY "MyPass@2026" REPLACE "oldpass"(带双引号,触发生成s:段)
真正卡住的地方往往不在密码本身,而在驱动版本、连接串语法、容器路由这三处——它们共同决定凭据能不能完整、准确地抵达认证模块。漏掉任意一环,ORA-01017 就照常报。











