【问题标题】:OPC UA Foundation SDK: Server does not have an instance certificate assignedOPC UA Foundation SDK:服务器没有分配实例证书
【发布时间】:2023-04-05 15:57:01
【问题描述】:

我正在使用带有 C# 的 Foundation SDK,尝试以最小的方式启动一个简单的服务器。

这是我目前的尝试。

public void StartServer()
{
    var config = new ApplicationConfiguration
    {
        ApplicationName = "TestServer",
        ApplicationType = ApplicationType.Client,
        SecurityConfiguration = new SecurityConfiguration
        {
            ApplicationCertificate = new CertificateIdentifier
            {
                StoreType = @"Windows", 
                StorePath = @"CurrentUser\My",
                SubjectName = Utils.Format(@"CN={0}, DC={1}", "TestServer", Dns.GetHostName())
            }, 
            TrustedPeerCertificates = new CertificateTrustList
            {
                StoreType = @"Windows", 
                StorePath = @"CurrentUser\TrustedPeople",
            }, 
            NonceLength = 32, 
            AutoAcceptUntrustedCertificates = true,
            ConfigureFirewall = false
        },
        TransportConfigurations = new TransportConfigurationCollection(),
        TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
        ServerConfiguration = new ServerConfiguration
        {
            SecurityPolicies = new ServerSecurityPolicyCollection
            {
                new ServerSecurityPolicy
                {
                    SecurityLevel = 0,
                    SecurityMode = MessageSecurityMode.None,
                    SecurityPolicyUri = "http://opcfoundation.org/UA/SecurityPolicy#None"
                }
            },
            UserTokenPolicies = new UserTokenPolicyCollection
            {
                new UserTokenPolicy { TokenType = UserTokenType.Anonymous }
            },
            DiagnosticsEnabled = true,
            MaxSessionCount = 100,
            MinSessionTimeout = 5000,
            MaxSessionTimeout = 10000,
            MaxBrowseContinuationPoints = 10,
            MaxQueryContinuationPoints = 10,
            MaxHistoryContinuationPoints = 100,
            MaxRequestAge = 600000,
            MinPublishingInterval = 100,
            MaxPublishingInterval = 3600000,
            PublishingResolution = 50,
            MaxSubscriptionLifetime = 3600000,
            MaxMessageQueueSize = 10,
            MaxNotificationQueueSize = 100,
            MaxNotificationsPerPublish = 1000,
            MinMetadataSamplingInterval = 1000
        }
    };
    config.Validate(ApplicationType.Server);

    var server = new MyCustomServer();

    server.Start(config);
}

当我尝试调用该方法时,出现以下异常:

Opc.Ua.ServiceResultException: Server does not have an instance certificate assigned.
   à Opc.Ua.ServerBase.OnServerStarting(ApplicationConfiguration configuration) dans ...\OPC Foundation\Stack\Core\Stack\Server\ServerBase.cs:ligne 1607
   à Opc.Ua.Server.StandardServer.OnServerStarting(ApplicationConfiguration configuration) dans ...\OPC Foundation\SampleApplications\SDK\Server\Server\StandardServer.cs:ligne 2628
   à Opc.Ua.ServerBase.Start(ApplicationConfiguration configuration) dans ...\OPC Foundation\Stack\Core\Stack\Server\ServerBase.cs:ligne 232
   à SlimFixtures.ServerDriver.StartServer() dans ...\ServerDriver.cs:ligne 71

我做错了什么?

【问题讨论】:

    标签: c# opc opc-ua


    【解决方案1】:

    所以你发现基于基础代码的服务器总是需要证书。 创建自签名证书很容易,如果您使用的是当前用户/我的 Windows 商店,则不需要管理员登录。

    验证后可以调用这个扩展方法:

    config.Validate(ApplicationType.Server);
    config.EnsureApplicationCertificate();
    

    其他地方

    public static class ServiceExtensions
    {
        /// <summary>
        /// Ensures the application certificate is present and valid.
        /// </summary>
        public static void EnsureApplicationCertificate(this ApplicationConfiguration configuration)
        {
            const ushort keySize = 1024;
            const ushort lifetimeInMonths = 300;
    
            if (configuration == null)
            {
                throw new ArgumentNullException("configuration");
            }
            bool errorFlag = false;
            string hostName = Dns.GetHostName();
            var serverDomainNames = configuration.GetServerDomainNames();
            var applicationCertificate = configuration.SecurityConfiguration.ApplicationCertificate;
            var certificate = applicationCertificate.Find(true);
            if (certificate != null)
            {
                // if cert found then check domains
                var domainsFromCertficate = Utils.GetDomainsFromCertficate(certificate);
                foreach (string serverDomainName in serverDomainNames)
                {
                    if (Utils.FindStringIgnoreCase(domainsFromCertficate, serverDomainName))
                    {
                        continue;
                    }
                    if (String.Equals(serverDomainName, "localhost", StringComparison.OrdinalIgnoreCase))
                    {
                        if (Utils.FindStringIgnoreCase(domainsFromCertficate, hostName))
                        {
                            continue;
                        }
                        var hostEntry = Dns.GetHostEntry(hostName);
                        if (hostEntry.Aliases.Any(alias => Utils.FindStringIgnoreCase(domainsFromCertficate, alias)))
                        {
                            continue;
                        }
                        if (hostEntry.AddressList.Any(ipAddress => Utils.FindStringIgnoreCase(domainsFromCertficate, ipAddress.ToString())))
                        {
                            continue;
                        }
                    }
                    Trace.TraceInformation("The application is configured to use domain '{0}' which does not appear in the certificate.", serverDomainName);
                    errorFlag = true;
                } // end for
                // if no errors and keySizes match
                if (!errorFlag && (keySize == certificate.PublicKey.Key.KeySize))
                {
                    return; // cert okay
                }
            }
            // if we get here then we'll create a new cert
            if (certificate == null)
            {
                certificate = applicationCertificate.Find(false);
                if (certificate != null)
                {
                    Trace.TraceInformation("Matching certificate with SubjectName '{0}' found but without a private key.", applicationCertificate.SubjectName);
                }
            }
            // lets check if there is any to delete
            if (certificate != null)
            {
                using (var store2 = applicationCertificate.OpenStore())
                {
                    store2.Delete(certificate.Thumbprint);
                }
            }
            if (serverDomainNames.Count == 0)
            {
                serverDomainNames.Add(hostName);
            }
            CertificateFactory.CreateCertificate(applicationCertificate.StoreType, applicationCertificate.StorePath, configuration.ApplicationUri, configuration.ApplicationName, null, serverDomainNames, keySize, lifetimeInMonths);
            Trace.TraceInformation("Created new certificate with SubjectName '{0}', in certificate store '{1}'.", applicationCertificate.SubjectName, applicationCertificate.StorePath);
            configuration.CertificateValidator.Update(configuration.SecurityConfiguration);
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      对于更新版本的库,有一个内置选项可以检查应用程序实例证书。它在 ApplicationInstance 类中可用。

      以下是您的使用方法:

      var applicationConfiguration = new ApplicationConfiguration
      {
          ApplicationName = "Aggregation server",
          ...
      };
      
      await applicationConfiguration.Validate(ApplicationType.ClientAndServer);
      
      var applicationInstance = new ApplicationInstance(applicationConfiguration);
      
      // This call will check that the application instance certificate exists, and will create it if not
      var result =
          await applicationInstance.CheckApplicationInstanceCertificate(false, CertificateFactory.defaultKeySize);
      
      var server = new AggregationServer();
      await applicationInstance.Start(server);
      System.Console.ReadKey();
      server.Stop();
      

      【讨论】:

        猜你喜欢
        • 2023-02-01
        • 2020-04-28
        • 1970-01-01
        • 1970-01-01
        • 2017-06-14
        • 1970-01-01
        • 1970-01-01
        • 2017-03-06
        • 1970-01-01
        相关资源
        最近更新 更多