ORA-28040报错因客户端与数据库加密协议不匹配。可在数据库sqlnet.ora中设置SQLNET.ALLOWED_LOGON_VERSION_SERVER=10(兼容老客户端),然后执行lsnrctlstop/start使配置生效。JDBCThin模式不读取该文件,需升级JDBC驱动并确保支持TLS1.2协议。
Oracle 12c连接ORA-28040版本不匹配?修改SQLNET.ALLOWED_LOGON_VERSION
作者:技术拾光
时间:2026-07-05
浏览:609
文章目录
SQLNET.ALLOWED_LOGON_VERSION_SERVER 参数,别用错了
这个参数是干嘛的?它告诉数据库:“最低能接受什么等级的老客户端来连我?” 值越小,能连的客户端越老,但安全风险也越大。需要特别注意的是,从 Oracle 12c R2 开始,那个不带后缀的老参数 `SQLNET.ALLOWED_LOGON_VERSION` 已经被废弃了,你写在配置文件里,Oracle 就当没看见,日志里你也查不到它。 具体怎么设,看你的实际环境: * **`SQLNET.ALLOWED_LOGON_VERSION_SERVER = 8`**:这个在 Oracle 12.2 以上版本已经不支持了,写了也没用。在 19c、21c 上,甚至可能导致启动报错或被直接跳过。 * **`SQLNET.ALLOWED_LOGON_VERSION_SERVER = 10`**:这是处理遗留系统时的稳妥选择。它能兼容 Oracle 10g、11g 的客户端(比如你手头还在用的 PL/SQL Developer、Toad,或者 ojdbc6.jar 驱动)。 * **`SQLNET.ALLOWED_LOGON_VERSION_SERVER = 12`**:适用于需要满足 19c 安全基线的场景。它会强制要求 TLS 1.2 协议和 SHA-2 密码校验,但同时,所有 11g 及更老的客户端都会被拒之门外。 记住,这个配置文件必须写在**数据库服务器**上,路径是 `$ORACLE_HOME/network/admin/sqlnet.ora`(Linux/Unix)或 `%ORACLE_HOME%\network\admin\sqlnet.ora`(Windows)。改自己电脑上或者应用服务器的配置文件,没用。改完参数,必须重启监听器,lsnrctl reload 不行
这是非常容易踩的坑。`SQLNET.ALLOWED_LOGON_VERSION_SERVER` 这个参数是监听器在启动时一次性读入的静态配置。你执行 `lsnrctl reload`,监听器并不会重新加载这个文件,相当于你改了个寂寞。
正确的操作是:
1. 执行 `lsnrctl stop`
2. 再执行 `lsnrctl start`
如果监听器重启失败,检查一下 `sqlnet.ora` 文件里是不是有语法错误,比如多了等号、引号没配对、等号前后不小心加了空格。
在某些 RAC 或配置严格的环境里,甚至需要先 `shutdown immediate;` 再 `startup;` 重启整个数据库实例,才能让新策略生效。改完之后怎么验证?随便连一次,然后去 `$ORACLE_HOME/network/log/listener.log` 里搜索 `Authentication protocol rejected` 之类的关键词,如果还有新记录,说明问题没解决。
JDBC 连不上还报错?别只盯着服务端参数
一个经典误区:服务端参数改好了,监听器也重启了,但程序用 JDBC 连接还是报 ORA-28040。为什么?因为**JDBC Thin 模式完全不读 `sqlnet.ora`**。它走的是自己驱动内部的协议栈和 JVM 的 TLS 支持。 即使你服务端设成了 `= 10`,下面这几个情况照样会触发报错: * **Classpath 污染**:项目里混着好几个版本的 Oracle 驱动 jar 包,比如同时有 `ojdbc6.jar` 和 `ojdbc8.jar`。 * **驱动版本太老**:你还在用 `ojdbc6.jar` 甚至更老的驱动?它不认识 12c 的新协议,也不会主动协商降级。官方建议至少用 `ojdbc7.jar`(JDK 7+)或 `ojdbc8.jar`(JDK 8+)。 * **JVM 没开启 TLSv1.2**:JDK 7/8 默认的 TLS 协议版本可能不够,需要在启动参数里加上 `-Dhttps.protocols=TLSv1.2`。JDK 11+ 默认开启,但如果有人显式禁用了,也会失败。 * **连接字符串写错了**:如果在 JDBC URL 里加了 `oracle.net.authentication_services=(NONE)`,虽然绕过了密码验证,但也把协议协商的流程给破坏了。OCI 模式下的 sqlnet.ora,真有那么灵吗?
用 Na vicat 这类工具的朋友,你得知道,Na vicat 默认走的是 JDBC Thin 模式,它跟你服务端的 `sqlnet.ora` 没关系。只有切到 OCI 模式,这个文件才可能发挥作用。但要让它真正生效,条件还挺苛刻: * Na vicat 里 OCI 设置路径,必须指向一个包含了 `oci.dll`(Windows)或 `libclntsh.so`(Linux)的目录。 * 这个目录下,也必须有一份和服务器上一致的、配好参数的 `sqlnet.ora` 文件(可以从服务器上复制一份过来)。 * 你用的 Instant Client 版本必须 ≥ 12.1,否则它也搞不定 12c+ 的协议协商。 * **文件编码是个巨大的隐患**:`sqlnet.ora` 的编码必须是 UTF-8 without BOM。如果编码不对,Oracle 会直接读取失败。最好用 vi 或者 Notepad++ 显式地另存为“ANSI”或“UTF-8 no BOM”格式。 很多看起来像是参数没设对的问题,根子都在这些细节上:你以为服务端改了就万事大吉,结果客户端根本没走那条路;或者你确实改了,但文件编码不对、路径被 `$TNS_ADMIN` 环境变量覆盖、监听器压根没重启……这些地方,比参数本身的值,更容易把整个排查过程堵死。实用工具推荐
电子包浆
使用 ›绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
图片压缩
使用 ›选择画质和输出格式,预览压缩前后的大小。