opc服务端
OpcUaServer.cs
using Opc.Ua; using Opc.Ua.Configuration; using Opc.Ua.Server; using System.Security.Cryptography.X509Certificates; namespace OpcServerCore.Util { public class OpcUaServer : StandardServer { public ApplicationInstance Application { get; private set; } public bool AutoAccept { get; set; } /// <summary> /// 认证方式 /// </summary> public UserTokenType UserTokenType { get; set; } /// <summary> /// 用户名 /// </summary> public string UserName { get; set; } = "admin"; /// <summary> /// 密码 /// </summary> public string Password { get; set; } = "123456"; ICertificateValidator m_userCertificateValidator; public OpcUaNodeManager OpcuaNode1 { get; set; } protected override MasterNodeManager CreateMasterNodeManager(IServerInternal server, ApplicationConfiguration configuration) { OpcuaNode1 = new OpcUaNodeManager(server, configuration); List<INodeManager> nodeManagers = new List<INodeManager>(); nodeManagers.Add(OpcuaNode1); return new MasterNodeManager(server, configuration, null, nodeManagers.ToArray()); } public async Task LoadAsync(string applicationName, string configSectionName) { try { CertificatePasswordProvider passwordProvider = new CertificatePasswordProvider(Password); Application = new ApplicationInstance { ApplicationName = applicationName, ApplicationType = ApplicationType.Server, ConfigSectionName = configSectionName, CertificatePasswordProvider = passwordProvider }; await Application.LoadApplicationConfiguration(false); } catch (Exception ex) { throw new Exception($"Load async error: {ex.Message}", ex); } } public async Task CheckCertificateAsync(bool renewCertificate) { try { ApplicationConfiguration config = Application.ApplicationConfiguration; if (renewCertificate) { await Application.DeleteApplicationInstanceCertificate(); } bool haveAppCertificate = await Application.CheckApplicationInstanceCertificate(false, minimumKeySize: 0); if (!haveAppCertificate) { throw new Exception("Application instance certificate invalid!"); } if (!config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } // 指定认证方式 config.ServerConfiguration.UserTokenPolicies.Clear(); UserTokenPolicy utp = new UserTokenPolicy(); utp.TokenType = UserTokenType; utp.PolicyId = utp.TokenType.ToString(); config.ServerConfiguration.UserTokenPolicies.Add(utp); for (int ii = 0; ii < config.ServerConfiguration.UserTokenPolicies.Count; ii++) { UserTokenPolicy policy = config.ServerConfiguration.UserTokenPolicies[ii]; if (policy.TokenType == UserTokenType.Certificate) { if (config.SecurityConfiguration.TrustedUserCertificates != null && config.SecurityConfiguration.UserIssuerCertificates != null) { CertificateValidator certificateValidator = new CertificateValidator(); certificateValidator.Update(config.SecurityConfiguration).Wait(); certificateValidator.Update(config.SecurityConfiguration.UserIssuerCertificates, config.SecurityConfiguration.TrustedUserCertificates, config.SecurityConfiguration.RejectedCertificateStore); m_userCertificateValidator = certificateValidator.GetChannelValidator(); } } } } catch (Exception ex) { throw new Exception($"CheckCertificateAsync: {ex.Message}", ex); } } /// <summary> /// Create server instance and add node managers. /// </summary> public void Create(IList<INodeManagerFactory> nodeManagerFactories) { try { if (nodeManagerFactories != null) { foreach (INodeManagerFactory factory in nodeManagerFactories) { this.AddNodeManager(factory); } } } catch (Exception ex) { throw new Exception($"Create Node manager Factories: {ex.Message}", ex); } } /// <summary> /// Start the server. /// </summary> public async Task StartAsync() { try { await Application.Start(this); this.CurrentInstance.SessionManager.ImpersonateUser += new ImpersonateEventHandler(ImpersonateUser); this.CurrentInstance.SessionManager.SessionActivated += EventStatus; this.CurrentInstance.SessionManager.SessionClosing += EventStatus; this.CurrentInstance.SessionManager.SessionCreated += EventStatus; } catch (Exception ex) { throw new Exception($"Start async: {ex.Message}", ex); } } /// <summary> /// Stops the server. /// </summary> public async Task StopAsync() { try { this.Stop(); } catch (Exception ex) { throw new Exception($"Stop async: {ex.Message}", ex); } } /// <summary> /// The certificate validator is used /// if auto accept is not selected in the configuration. /// </summary> private void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e) { if (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted) { if (AutoAccept) { Logger.Info($"Accepted Certificate: [{e.Certificate.Subject}] [{e.Certificate.Thumbprint}]"); e.Accept = true; return; } } Logger.Info($"Rejected Certificate: {e.Error} [{e.Certificate.Subject}] [{e.Certificate.Thumbprint}]"); } private void EventStatus(Session session, SessionEventReason reason) { } private void ImpersonateUser(Session session, ImpersonateEventArgs args) { UserNameIdentityToken? userNameToken = args.NewIdentity as UserNameIdentityToken; if (userNameToken != null) { args.Identity = VerifyPassword(userNameToken); return; } X509IdentityToken? x509Token = args.NewIdentity as X509IdentityToken; if (x509Token != null) { VerifyUserTokenCertificate(x509Token.Certificate); args.Identity = new UserIdentity(x509Token); Utils.Trace("X509 Token Accepted: {0}", args.Identity.DisplayName); return; } } /// <summary> /// Validates the password for a username token. /// </summary> private IUserIdentity VerifyPassword(UserNameIdentityToken userNameToken) { var userName = userNameToken.UserName; var password = userNameToken.DecryptedPassword; if (string.IsNullOrEmpty(userName)) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, "Security token is not a valid username token. An empty username is not accepted."); } if (string.IsNullOrEmpty(password)) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenRejected, "Security token is not a valid username token. An empty password is not accepted."); } if (!(userName == "admin" && password == "123456")) { TranslationInfo info = new TranslationInfo("InvalidPassword", "en-US", "Invalid username or password.", userName); throw new ServiceResultException(new ServiceResult(StatusCodes.BadUserAccessDenied, "InvalidPassword", "http://opcfoundation.org/Quickstart/ReferenceServer/v1.03", new LocalizedText(info))); } return new UserIdentity(userNameToken); } /// <summary> /// Verifies that a certificate user token is trusted. /// </summary> private void VerifyUserTokenCertificate(X509Certificate2 certificate) { try { if (m_userCertificateValidator != null) { m_userCertificateValidator.Validate(certificate); } else { new CertificateValidator().Validate(certificate); } } catch (Exception e) { TranslationInfo info; StatusCode result = StatusCodes.BadIdentityTokenRejected; ServiceResultException se = e as ServiceResultException; if (se != null && se.StatusCode == StatusCodes.BadCertificateUseNotAllowed) { info = new TranslationInfo("InvalidCertificate", "en-US", "'{0}' is an invalid user certificate.", certificate.Subject); result = StatusCodes.BadIdentityTokenInvalid; } else { info = new TranslationInfo("UntrustedCertificate", "en-US", "'{0}' is not a trusted user certificate.", certificate.Subject); } throw new ServiceResultException(new ServiceResult(result, info.Key, "http://opcfoundation.org/Quickstart/ReferenceServer/v1.04", new LocalizedText(info))); } } } }
qq:505645074