我有一个控制台应用程序正在尝试使用钱包连接到远程 Oracle 数据库进行身份验证。这是连接代码。
OracleConfiguration.WalletLocation = @"(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=c:\Oracle\wallets\test)))";
OracleConfiguration.SqlNetWalletOverride = true;
OracleConfiguration.TnsAdmin = @"C:\Oracle";
OracleConfiguration.TraceLevel = 7;
OracleConfiguration.TraceFileLocation = @"C:\Oracle\trace";
OracleConfiguration.TraceOption = 7;
using (var dbConn = new OracleConnection(connectionString))
{
dbConn.Open();
Console.WriteLine("SUCCESS!");
dbConn.Close();
}
钱包中的证书是由我尝试连接的对方自签名的。连接失败并出现以下错误:
Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-00542: Failure during SSL handshake
---> OracleInternal.Network.NetworkException (0x80004005): ORA-00542: Failure during SSL handshake
---> System.Security.Authentication.AuthenticationException: The remote certificate was rejected by the provided RemoteCertificateValidationCallback.
在其他 .NET 应用程序中,我已经能够分配回调来处理服务器证书验证错误。有没有办法在 Oracle 连接的上下文中执行此操作?
Oracle 连接可以配置为接受自签名证书手动添加到 Windows 中的受信任根证书颁发机构。还可以通过编程方式添加证书。
截至 2024 年,Oracle.ManagedDataAccess.Core v23.6.0 OracleInternal.Network.TcpsTransportAdapter 类 Negotiate 方法直接引用私有 RemoteCertificateValidationCallback 方法 ValidateRemoteCertificate,该方法可能不应使用 Lib.Harmony v2.3.3 或类似方法替换:
using HarmonyLib; // 2024 - Lib.Harmony v2.3.3
using Oracle.ManagedDataAccess.Client; // v23.6.0
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public class OverrideCertificateValidationCallback
{
// Assign a callback to handle ODP.NET server certificate validation errors
// https://stackoverflow.com/a/79151177/423430
public static RemoteCertificateValidationCallback CertificateValidationCallback { get; set; }
static OverrideCertificateValidationCallback()
{
using var ensureLoaded = new OracleConnection();
// Patching > Postfix > change the result of the original method
// https://harmony.pardeike.net/articles/patching-postfix.html
new Harmony(nameof(OverrideCertificateValidationCallback))
.Patch(AccessTools.Method(AccessTools.TypeByName("OracleInternal.Network.TcpsTransportAdapter"),
"ValidateRemoteCertificate"), postfix: new(OracleTcpsTransportAdapter_ValidateRemoteCertificate));
}
// OracleInternal.Network.TcpsTransportAdapter Negotiate directly references private method ValidateRemoteCertificate
// (2024 - Oracle.ManagedDataAccess.Core v23.6.0)
public static void OracleTcpsTransportAdapter_ValidateRemoteCertificate
(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors pErrs, ref bool __result) =>
__result = (CertificateValidationCallback?.Invoke(sender, cert, chain, pErrs)).GetValueOrDefault(__result);
}