如何在C#开发的OPC UA服务器中区分正向与反向连接并配置令牌策略
OPC UA服务器连接类型区分与身份令牌策略控制方案
核心思路
通过OPC Foundation .NET SDK提供的会话连接属性判断正向/反向连接,在SessionManager_ImpersonateUser事件中针对不同连接类型执行对应的身份令牌校验逻辑:反向连接仅允许匿名身份,正向连接支持匿名、用户名密码、证书三种策略。
步骤1:判断连接类型
利用Session对象的TransportConnection.IsReverseConnection属性,直接标识当前会话是否为反向连接(客户端主动发起ReverseHello建立的连接)。
步骤2:实现ImpersonateUser事件逻辑
在事件处理方法中,根据连接类型校验客户端提交的身份令牌,拒绝不符合策略的请求:
private void SessionManager_ImpersonateUser(Session session, ImpersonateUserEventArgs args) { // 区分正向/反向连接 bool isReverseConnection = session.TransportConnection.IsReverseConnection; UserIdentityToken requestToken = args.NewIdentity; UserTokenType tokenType = requestToken.Type; if (isReverseConnection) { // 反向连接仅允许Anonymous令牌 if (tokenType != UserTokenType.Anonymous) { args.ErrorStatus = StatusCodes.BadUserAccessDenied; args.ErrorMessage = "反向连接仅支持匿名身份验证"; return; } // 匿名验证通过,设置会话身份 args.Identity = new UserIdentity(new AnonymousIdentityToken()); args.ErrorStatus = StatusCodes.Good; } else { // 正向连接支持三种令牌策略,分别处理 switch (tokenType) { case UserTokenType.Anonymous: args.Identity = new UserIdentity(new AnonymousIdentityToken()); args.ErrorStatus = StatusCodes.Good; break; case UserTokenType.UserName: var usernameToken = requestToken as UserNameIdentityToken; if (ValidateUsernameCredentials(usernameToken.UserName, usernameToken.DecryptedPassword)) { args.Identity = new UserIdentity(usernameToken); args.ErrorStatus = StatusCodes.Good; } else { args.ErrorStatus = StatusCodes.BadUserAccessDenied; args.ErrorMessage = "用户名或密码无效"; } break; case UserTokenType.Certificate: var certToken = requestToken as X509IdentityToken; if (ValidateClientCertificate(certToken.Certificate)) { args.Identity = new UserIdentity(certToken); args.ErrorStatus = StatusCodes.Good; } else { args.ErrorStatus = StatusCodes.BadCertificateUntrusted; args.ErrorMessage = "客户端证书未被信任"; } break; default: args.ErrorStatus = StatusCodes.BadUserAccessDenied; args.ErrorMessage = "不支持的身份令牌类型"; break; } } } // 用户名密码验证逻辑示例 private bool ValidateUsernameCredentials(string username, string password) { // 替换为实际业务逻辑:比如从配置文件、数据库读取校验 return username.Equals("authorized_user", StringComparison.OrdinalIgnoreCase) && password.Equals("secure_pass123"); } // 客户端证书验证逻辑示例 private bool ValidateClientCertificate(X509Certificate2 certificate) { // 替换为实际逻辑:比如检查证书是否在服务器信任存储、证书链有效 return certificate.Subject.Contains("TrustedClient") && certificate.Verify(); }
步骤3:配置反向连接端点(可选但推荐)
在服务器初始化时,为反向连接配置专门的端点,并限制其仅支持匿名令牌策略,从源头减少非法请求:
// 初始化服务器配置时添加反向连接端点 var reverseEndpoint = new EndpointDescription { EndpointUrl = "opc.tcp://localhost:62542/ReverseConnect", SecurityMode = MessageSecurityMode.SignAndEncrypt, // 根据业务需求设置安全模式 SecurityPolicyUri = SecurityPolicies.Basic256Sha256, // 仅允许Anonymous令牌策略 UserTokenPolicies = new List<UserTokenPolicy> { new UserTokenPolicy { TokenType = UserTokenType.Anonymous, PolicyId = "ReverseAnonymousPolicy" } } }; // 将反向端点添加到服务器配置 server.Configuration.Endpoints.Add(reverseEndpoint);
关键说明
TransportConnection.IsReverseConnection是SDK原生属性,无需额外开发即可准确识别连接方向;- 在
ImpersonateUser事件中处理身份变更请求,覆盖客户端会话期间的身份切换场景; - 反向连接的双重校验:端点配置限制+事件逻辑校验,确保策略严格执行。
内容的提问来源于stack exchange,提问作者Prabs
相关产品推荐
相关产品推荐

