Python连接Basic256Sha256安全策略OPC UA服务器报错求助
解决OPC UA Basic256Sha256安全策略下的Python客户端连接问题
问题诊断
从错误BadSecurityChecksFailed和超时日志来看,核心问题是客户端证书未通过服务器的安全校验——即便你已在服务器信任了test.com证书,仍可能存在以下疏漏:
- 生成的客户端证书不符合OPC UA规范要求
- 客户端未信任服务器的证书
- 安全参数配置不完整
修正步骤
1. 生成符合OPC UA规范的客户端证书
你的现有证书生成脚本缺少OPC UA强制要求的扩展字段(如密钥用法、主题备用名称),下面是基于cryptography库的修正脚本(该库比pyOpenSSL更易维护且符合现代加密标准):
from cryptography import x509 from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import rsa from datetime import datetime, timedelta def generate_opcua_certs(): # 生成2048位RSA私钥 private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, ) # 设置证书主体与颁发者(自签名) subject = issuer = x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Beijing"), x509.NameAttribute(NameOID.LOCALITY_NAME, "Beijing"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PythonOPCUAClient"), x509.NameAttribute(NameOID.COMMON_NAME, "PythonUA_Client"), ]) # 构建符合OPC UA规范的证书 cert = x509.CertificateBuilder().subject_name( subject ).issuer_name( issuer ).public_key( private_key.public_key() ).serial_number( x509.random_serial_number() ).not_valid_before( datetime.utcnow() ).not_valid_after( datetime.utcnow() + timedelta(days=365) ).add_extension( x509.SubjectAlternativeName([x509.DNSName("localhost")]), critical=False, ).add_extension( x509.KeyUsage( digital_signature=True, key_encipherment=True, content_commitment=True, data_encipherment=False, key_agreement=False, key_cert_sign=False, crl_sign=False, encipher_only=False, decipher_only=False ), critical=True, ).add_extension( x509.ExtendedKeyUsage([ExtendedKeyUsageOID.CLIENT_AUTH]), critical=False, ).sign(private_key, hashes.SHA256()) # 保存私钥与证书 with open("client_key.pem", "wb") as f: f.write(private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption() )) with open("client_cert.pem", "wb") as f: f.write(cert.public_bytes(serialization.Encoding.PEM)) print("OPC UA合规证书生成完成") if __name__ == "__main__": generate_opcua_certs()
2. 处理服务器DER格式证书
需要将服务器的.der证书转换为PEM格式,供客户端信任:
# 使用openssl命令转换(Windows需安装OpenSSL工具) openssl x509 -inform der -in server_cert.der -out server_cert.pem
3. 修正客户端连接代码
补充服务器信任证书路径,并调整超时参数适配工业服务器:
from opcua import Client, ua url = "opc.tcp://srvbeathcs01:44683/ABB/800xA/OPC/UA/Server" client = Client(url) # 安全字符串格式:<安全策略>,<安全模式>,<客户端证书>,<客户端私钥>,<信任的服务器证书> client.set_security_string("Basic256Sha256,Sign,client_cert.pem,client_key.pem,server_cert.pem") # 针对ABB服务器设置更长超时 client.session_timeout = 30000 client.connect_timeout = 30000 try: client.connect() print(f"Connected to: {url}") servicelevel_node = client.get_node("ns=2;b=ADwDSDdc1EO/1/EufyBvM8qrOcZ9hX9NnGQgzR8uGN1FbmVyZ2llRWxlYy5Db21wdGV1cjkudWludDI=") servicelevel_node_value = servicelevel_node.get_value() print(servicelevel_node_value) finally: client.disconnect()
4. 服务器端证书信任确认
确保在ABB 800xA的OPC UA服务器配置中,已将生成的client_cert.pem导入信任证书列表,且启用了匿名认证+Sign消息模式。
关键注意事项
- OPC UA证书必须包含规范要求的扩展字段,否则服务器会直接拒绝连接
- 客户端必须信任服务器证书,双向验证是Basic256Sha256策略的强制要求
- ABB 800xA服务器对证书合规性要求严格,需避免使用简化版自签名证书
内容的提问来源于stack exchange,提问作者SinizowN
相关产品推荐
相关产品推荐

