使用asyncua连接OPC UA服务器遇BadSecurityPolicyRejected及协程问题
尝试使用Python的asyncua库连接OPC UA服务器(地址:opc.tcp://172.16.0.1:4844),采用Basic256Sha256安全策略及客户端证书认证时,出现以下警告与错误:
Connecting to opc.tcp://172.16.0.1:4844...
C:\Users\Administrator\PycharmProjects\PythonProject1\intro.py:272: RuntimeWarning: coroutine 'Client.set_security_string' was never awaited
client.set_security_string(f"Basic256Sha256,SignAndEncrypt,{cert_path},{key_path}")
RuntimeWarning: Enable tracemalloc to get the object allocation traceback ServiceFault (BadSecurityPolicyRejected, diagnostics: DiagnosticInfo(SymbolicId=None, NamespaceURI=None, Locale=0, LocalizedText=None, AdditionalInfo=None, InnerStatusCode=None, InnerDiagnosticInfo=None))
from server received in response to CreateSessionRequest Error: The security policy does not meet the requirements set by the server.(BadSecurityPolicyRejected)
Updated status of server ID None to 'Not Running'. Inserted action log for Server ID None: Not Running in 172.16.0.1
使用的核心代码片段:
for server in servers: endpoint_url = server.EndpointUrl server_ip = server.ServerIP print(f"Connecting to {endpoint_url}...") if not ping_server(server_ip): print(f"{server_ip} is not reachable.") update_server_status(cursor, None, "Not Running", server_ip) continue try: # Configure OPC UA client client = Client(endpoint_url) client.set_user("DEWA_OPC") client.set_password("RTeK8QrF9F5G") client.set_security_string(f"Basic256Sha256,SignAndEncrypt,{cert_path},{key_path}") await client.connect() # Await the connection print(f"Connected to OPC UA server at {endpoint_url}") # 后续数据获取逻辑... await client.disconnect() # Await disconnection print("Real-time data fetch cycle completed.") except Exception as e: print(f"Error: {e}") update_server_status(cursor, None, "Not Running", server_ip)
已完成验证:
- 确认服务器支持Basic256Sha256安全策略;
- 确认cert_path和key_path指向有效文件;
- 怀疑误用了set_security_string方法。
咨询问题:
- 异步环境中如何正确使用set_security_string()?
- 导致BadSecurityPolicyRejected错误的原因可能是什么?
1. 异步环境下正确使用set_security_string()
set_security_string是asyncua库中的协程方法,必须通过await关键字调用,否则会触发"coroutine was never awaited"警告,同时安全配置不会生效,这也是后续出现安全策略错误的潜在原因之一。
修正后的代码:
client = Client(endpoint_url) client.set_user("DEWA_OPC") client.set_password("RTeK8QrF9F5G") # 关键修正:添加await调用协程 await client.set_security_string(f"Basic256Sha256,SignAndEncrypt,{cert_path},{key_path}") await client.connect()
注意:该配置必须在await client.connect()之前执行,确保连接建立前安全策略已生效。
2. BadSecurityPolicyRejected错误的可能原因
即使服务器支持Basic256Sha256,仍可能因为以下原因触发该错误:
- 安全模式不匹配:你使用的
SignAndEncrypt模式可能未被服务器允许。尝试切换为SignOnly或EncryptOnly测试:await client.set_security_string(f"Basic256Sha256,SignOnly,{cert_path},{key_path}") - 证书未被服务器信任:多数OPC UA服务器需要手动将客户端证书导入信任列表,即使证书文件有效,未被信任也会被拒绝连接。检查服务器的证书信任配置,确保你的客户端证书已添加到信任列表中。
- 安全策略名称格式错误:部分服务器要求使用完整的安全策略URI而非简写,尝试替换为完整URI:
await client.set_security_string(f"http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256,SignAndEncrypt,{cert_path},{key_path}") - 混合认证冲突:同时设置用户名密码认证和证书认证,部分服务器不支持两种认证方式共存。尝试移除
set_user和set_password的配置,仅保留证书认证测试。
内容的提问来源于stack exchange,提问作者AC19UCS131 Varsha N

