ORA-28040错误源于Java客户端与Oracle服务端加密握手协议不匹配,须在数据库服务器端$ORACLE_HOME/network/admin/sqlnet.ora中配置SQLNET.ALLOWED_LOGON_VERSION_SERVER=10并重启监听器,同时确保JDBC驱动单一(如ojdbc8.jar)且JVM启用TLSv1.2。
ora-28040 不是驱动没加对,也不是密码错了,而是客户端(java 应用)和 oracle 数据库服务端在“用哪套加密规则握手”这件事上彻底谈崩了。解决它,必须从服务端 sqlnet.ora 入手,而不是换驱动、改 url 或重装客户端。
改哪个文件?改数据库服务器上的 sqlnet.ora
这个参数只在数据库服务端生效,客户端改了完全没用。常见误操作是:开发在自己电脑上改了本地 sqlnet.ora,然后抱怨“配置写了还是连不上”。你必须登录数据库服务器,找到真实路径:
-
$ORACLE_HOME/network/admin/sqlnet.ora(Linux/Unix 单实例或 RAC 的 database 软件目录下) - 别进
$GRID_HOME或客户端安装目录 —— 那些路径下的文件对服务端连接无影响 - 如果
$TNS_ADMIN环境变量被设置,监听器会优先读那个路径,得一并检查
SQLNET.ALLOWED_LOGON_VERSION_SERVER 设多少才安全又可用
值越小兼容性越强,但安全风险越高。Oracle 12c R2 及以后已废弃 SQLNET.ALLOWED_LOGON_VERSION(无后缀),继续用会刷屏告警日志。
-
SQLNET.ALLOWED_LOGON_VERSION_SERVER = 10:兼容 Oracle 10g/11g 客户端,包括 PL/SQL Developer、Toad、老版 JDBC(如ojdbc6),是生产环境较稳妥的起点 -
SQLNET.ALLOWED_LOGON_VERSION_SERVER = 11:仅允许 12c+ 客户端,安全性更高,但会直接拒绝 11g 客户端 -
SQLNET.ALLOWED_LOGON_VERSION_SERVER = 8:理论上兼容最老系统,但 Oracle 12.2+ 已移除对该值的支持,设了也无效;19c/21c 更是完全不认
示例配置(追加到 sqlnet.ora 文件末尾即可):
SQLNET.ALLOWED_LOGON_VERSION_SERVER = 10
改完必须重启监听器,lsnrctl reload 不行
这个参数是监听器启动时一次性加载的静态配置,lsnrctl reload 不会重新读取。不重启,等于没改。
立即学习“Java免费学习笔记(深入)”;
- 执行
lsnrctl stop→lsnrctl start - 确认监听器已加载新配置:用
lsnrctl status查看输出中是否包含 “Listening Endpoints Summary”,再连一次测试 - 如果监听器启不来,检查
sqlnet.ora是否有语法错误(比如多了一个等号、引号不配对)
JDBC 应用仍报 ORA-28040?先查 classpath 里有没有混驱动
即使服务端设了 = 10,Java 应用仍报 ORA-28040,大概率是 classpath 里混进了多个版本的 Oracle 驱动 jar。
- 确保只保留一个驱动:推荐
ojdbc8.jar(JDK 8+)或ojdbc11.jar(JDK 11+),别用ojdbc6 - JVM 启动加参数:
-Dhttps.protocols=TLSv1.2(尤其 JDK 7/8 默认不启用 TLS 1.2) - 检查连接 URL 是否含
?oracle.net.authentication_services=(NONE)——这会绕过密码验证,但也会触发协议协商异常 - Spring Boot 用户注意:
application.properties里别硬编码过时的oracle.jdbc.thinLogonVersion参数
真正容易被忽略的是:改了服务端配置后,如果用户密码是在旧协议下创建的(比如只存了 10g verifier),即使协议放行,仍可能触发后续的 ORA-01017。这时需要重置密码,让数据库生成新协议所需的 verifier。


















