我对 OPC UA 协议还很陌生;我最近编写了一个 C 接口来使用 OPCFoundation 的库连接到一些机器,到目前为止我不必处理证书,因为所有机器都允许不安全的连接。
现在连接到使用证书的计算机,我应该如何修改我的代码以模拟我可以在 UAEExpert 软件上执行的“信任服务器证书”操作,该操作会警告证书,但允许我信任来自的证书机器(将其保存到本地文件夹)并继续会话?
在我的代码中,我有
"AutoAcceptUntrustedCertificates = true"
,但是当我尝试打开会话时,我得到了
Opc.Ua.ServiceResultException “证书不可信。 主题名称:[电子邮件受保护] ...”
提前致谢
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Configuration;
private static String CallOpcUA(string indirizzoMacchina, string displayNome, string idNodo)
{
var config = new ApplicationConfiguration()
{
ApplicationName = "MyApp",
ApplicationUri = Utils.Format(@"urn:{0}:MyApp", System.Net.Dns.GetHostName()),
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\MachineDefault", SubjectName = "MyApp" },
TrustedIssuerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Certificate Authorities" },
TrustedPeerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Applications" },
RejectedCertificateStore = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\RejectedCertificates" },
AutoAcceptUntrustedCertificates = true
},
TransportConfigurations = new TransportConfigurationCollection(),
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 },
TraceConfiguration = new TraceConfiguration()
};
config.Validate(ApplicationType.Client).GetAwaiter().GetResult();
if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
{
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); };
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateTimeInvalid); };
}
var application = new ApplicationInstance
{
ApplicationName = "MyApplication",
ApplicationType = ApplicationType.Client,
ApplicationConfiguration = config
};
try
{
application.CheckApplicationInstanceCertificate(false, 2048).GetAwaiter().GetResult();
}
catch (System.IO.FileLoadException e)
{
}
try
{
identity = new UserIdentity();
var selectedEndpoint = CoreClientUtils.SelectEndpoint(indirizzoMacchina, useSecurity: false);
using (var session = Session.Create(config, new ConfiguredEndpoint(null, selectedEndpoint, EndpointConfiguration.Create(config)), false, "", 60000, identity, null).GetAwaiter().GetResult())
{
[read value from the node]
}
}
catch (Opc.Ua.ServiceResultException e)
{
}
}
使用 OPC UA 安全端点,您必须始终提供客户端证书。您不能省略此证书,并且服务器的信任列表中应包含此证书。否则服务器可能会拒绝您的连接。
我在您的代码中看不到您提供的客户端证书。
您无法使用客户端 AutoAcceptUntrustedCertificates=true 覆盖此设置。
这对于问题的作者来说可能为时已晚,但可能对其他人有帮助。
尝试添加一个自动接受不受信任证书的证书验证器:
var config = new ApplicationConfiguration()
{
ApplicationName = "MyApp",
ApplicationUri = Utils.Format(@"urn:{0}:MyApp", System.Net.Dns.GetHostName()),
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\MachineDefault", SubjectName = "MyApp" },
TrustedIssuerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Certificate Authorities" },
TrustedPeerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Applications" },
RejectedCertificateStore = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\RejectedCertificates" },
AutoAcceptUntrustedCertificates = true
},
TransportConfigurations = new TransportConfigurationCollection(),
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 },
TraceConfiguration = new TraceConfiguration(),
// ***** ADD THIS ***** //
CertificateValidator = new CertificateValidator() { AutoAcceptUntrustedCertificates = true },
};
作为快速修复,替换此:
if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
{
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); };
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateTimeInvalid); };
}
为此:
if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
{
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = true; };
}
它对我来说适用于多个不同的服务器。
我想在 VB.net 中执行此操作,但出现错误:
config.Validate(ApplicationType.Client).GetAwaiter().GetResult()
If config.SecurityConfiguration.AutoAcceptUntrustedCertificates Then
AddHandler config.CertificateValidator.CertificateValidation, Sub(s, e) e.Accept = e.Error.StatusCode = StatusCodes.BadCertificateUntrusted
End If
Lambda 参数 '' 隐藏封闭块中的变量、先前定义的范围变量或查询表达式中隐式声明的变量。