Oracle 11g与EF Core 8连接异常:PROD服务器报ORA-28040错误求助
问题场景
两台同版本(11.2.0.4)的Oracle 11g服务器,使用.NET 8 + EF Core 8.0.7 + Oracle.EntityFrameworkCore v8.23.50项目连接时,TEST实例可正常访问,但PROD实例抛出认证错误:
OracleException: ORA-28040: The database does not accept your client's authentication protocol; login denied.
当前配置
DbContext初始化代码
builder.Services.AddDbContext<AppDbContext>(options => { options.UseOracle(builder.Configuration.GetConnectionString("test"), x => x.UseOracleSQLCompatibility( Microsoft.EntityFrameworkCore.OracleSQLCompatibility.DatabaseVersion19 )).EnableSensitiveDataLogging() .LogTo(Console.WriteLine, LogLevel.Information); }, ServiceLifetime.Singleton);
连接字符串(已通过Oracle SQL Developer、Oracle.ManagedDataAccess.Client验证有效)
"prod": "User Id=***;Password=****;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=productionIP)(PORT=****)))(CONNECT_DATA=(SERVICE_NAME=prod)));" "test": "User Id=***;Password=****;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=testIP)(PORT=****)))(CONNECT_DATA=(SERVICE_NAME=test)));"
服务器配置说明
两台服务器的SQLNET.ORA、listener.ora、tnsnames.ora配置完全一致,且均可通过其他客户端正常访问。
已验证的可行连接方式
- 使用EF Core 7并设置
OracleSQLCompatibility.DatabaseVersion11,可正常连接两台服务器 - 直接使用
Oracle.ManagedDataAccess.Client连接,可正常访问两台服务器
解决方案建议
1. 修正Oracle SQL兼容性版本
当前代码指定了DatabaseVersion19,但目标数据库是Oracle 11g,这会使客户端采用更高版本的认证协议,而PROD服务器可能对协议版本限制更严格。将兼容性版本改为11g对应选项:
// 针对PROD连接的配置示例 options.UseOracle(builder.Configuration.GetConnectionString("prod"), x => x.UseOracleSQLCompatibility(Microsoft.EntityFrameworkCore.OracleSQLCompatibility.DatabaseVersion11))
建议统一为所有Oracle 11g连接设置该兼容性版本,避免版本不匹配。
2. 检查PROD服务器的认证协议限制
尽管配置文件内容一致,但PROD服务器的实际生效配置可能存在差异。检查SQLNET.ORA中的SQLNET.ALLOWED_LOGON_VERSION_SERVER参数:
- 若该参数值为12或更高,会拒绝11g版本的认证协议
- 修改为允许11g协议:
SQLNET.ALLOWED_LOGON_VERSION_SERVER = 11
修改后需重启数据库监听服务和实例。
3. 调整Oracle.EntityFrameworkCore版本
Oracle.EntityFrameworkCore v8.23.50主要针对Oracle 12c及以上版本优化,对11g的支持有限。可尝试降级到与EF Core 7兼容的版本(如v7.23.xx),同时保持项目基于.NET 8(部分版本兼容)。
4. 连接字符串中强制指定认证协议
在PROD的连接字符串中添加AUTHENTICATION_PROTOCOL=11参数,强制客户端使用11g认证协议:
"prod": "User Id=***;Password=****;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=productionIP)(PORT=****)))(CONNECT_DATA=(SERVICE_NAME=prod)));AUTHENTICATION_PROTOCOL=11;"
内容的提问来源于stack exchange,提问作者Koala163

