我是opc ua的新手,不是java的Maven。在java中设置客户机时,我在证书处理方面遇到了问题。我想通过basic 256,signandencrypt连接到服务器。据我所知,在这个安全阶段,由客户机创建或加载的证书被发送到服务器,在那里它必须被接受。然后服务器将证书发送回客户机,然后客户机需要接受该证书。如果我错了,请纠正我。
在客户端创建/加载证书并将其发送到服务器已经可以正常工作(请参阅下面的代码),然后我可以在服务器端手动接受它。但在那之后,我陷入了困境:如何在代码中看到这个证书验证,如何找到服务器证书,更不用说接受它了?在实现过程中,我使用opc-ua的sampleconsoleclient进行了一些定位。但与此相反,我不使用任何用户输入。
这是我目前的一些代码。
初始化:
try {
client = new UaClient(serverUri);
} catch (final URISyntaxException e) {
throw new InitializationException("The server uri has an invalid syntax.", e);
}
try {
client.setApplicationIdentity(createApplicationIdentity());
} catch (final SecureIdentityException e) {
throw new InitializationException(
"Application Identity could not be created due to a Security Identity Exception.", e);
} catch (final IOException e) {
throw new InitializationException("Application Identity could not be created due to an IO Exception.",
e);
}
createapplicationidentity():
final ApplicationDescription appDescription = new ApplicationDescription();
appDescription.setApplicationName(new LocalizedText(APPLICATION_NAME, Locale.ENGLISH));
appDescription.setApplicationUri(APPLICATION_URI);
appDescription.setProductUri(PRODUCT_URI);
appDescription.setApplicationType(ApplicationType.Client);
// Setting security features
client.setSecurityMode(SecurityMode.BASIC256_SIGN_ENCRYPT);
client.setCertificateValidator(validator);
validator.setValidationListener(myValidationListener); //myValidationListener is similar to most lines in MyCertificateValidationListener in the opc ua samples
final File privatePath = new File(validator.getBaseDir(), "private");
final KeyPair issuerCertificate = null;
final int[] keySizes = null;
final ApplicationIdentity identity = ApplicationIdentity.loadOrCreateCertificate(appDescription,
"Sample Organisation", "opcua", privatePath, issuerCertificate, keySizes, true);
identity.setApplicationDescription(appDescription);
return identity;
在初始化之后,我尝试这样连接(通过注解,我想象连接可以正常工作):
final String securityPolicy = client.getEndpoint() == null
? client.getSecurityMode().getSecurityPolicy().getPolicyUri()
: client.getEndpoint().getSecurityPolicyUri();
client.setSessionName(String.format("%s@%s/Session%d", APPLICATION_NAME,
ApplicationIdentity.getActualHostNameWithoutDomain(), ++sessionCount));
try {
//Idea: catch the server certificate and accept it. Only if that was possible: connect
client.connect();
} catch (final ServiceException e) {
e.printStackTrace();
}
client.setKeepSubscriptions(false);
// After that resolving namespace index (works fine)
}
以及抛出的错误:
WARN (?:?): /<IPofServer> Error org.opcfoundation.ua.common.ServiceResultException: Bad_SecurityChecksFailed
(0x80130000) "An error occurred verifying security." at
org.opcfoundation.ua.transport.tcp.io.TcpConnection$ReadThread.run(Unknown Source)
com.prosysopc.ua.client.ConnectException: Failed to create secure channel to server: : opc.tcp://<IPofServer>
[http://opcfoundation.org/UA/SecurityPolicy#Basic256,SignAndEncrypt]
ServiceResult=Bad_SecurityChecksFailed (0x80130000) "An error occurred verifying security."
at com.prosysopc.ua.client.UaClient.n(Unknown Source)
at com.prosysopc.ua.client.UaClient.connect(Unknown Source)
at *lineOfCode*
Caused by: org.opcfoundation.ua.common.ServiceResultException:
Bad_SecurityChecksFailed (0x80130000) "An error occurred verifying security."
at org.opcfoundation.ua.transport.tcp.io.TcpConnection$ReadThread.run(Unknown Source)
代码行是 client.connect()
.
提前谢谢你的帮助!!
3条答案
按热度按时间izj3ouym1#
谢谢大家的回答。在此期间,我基本上尝试了复制/粘贴和修改
connect()
以及initalize()
prosyssdk示例中sampleconsoleclient中的方法。我猜这和更新一些信息有关,但我不太确定。。。事实上,我的申请正在进行中,但谢谢你的努力!omvjsjqw2#
很明显,您指的是prosys opc ua java sdk。
当您第一次尝试建立安全连接时,通常首先发生的是,服务器将拒绝访问您的客户端应用程序,并返回bad\u securitychecksfiled。
只有在告诉服务器信任(客户机应用程序的证书)之后,才能进入客户机应用程序将尝试验证服务器证书的阶段,并触发“validationlistener”。
iyr7buue3#
服务器将把它的证书发送给客户端。然后客户必须
验证证书的有效性。这相当于验证证书的签名、检查有效性、证书中的主机名是否与端点中的主机名匹配、检查crl等等。通常sdk(验证器)应该为您完成这项工作,但是您可能需要向验证器提供一些参数,以便实际执行哪些检查。安全策略basic256对证书施加了一些最低要求,当然,证书应该满足这些要求。您可以在此处查看要求:http://opcfoundation-onlineapplications.org/profilereporting/ --转到安全类别->面->安全策略。
检查服务器证书是否可信。这通常相当于检查(puclic key)证书的副本是否已放入选择为信任存储的某个证书存储中。如果您编写客户机,则由您决定选择哪个存储,但您需要告诉验证器在哪里查找。我对opc-ua在java中的开发不太了解,但是您应该检查验证器希望存储哪些证书。可能有一个默认的密钥文件。
(在服务器端,客户端证书也是如此)。
这假设您是从自签名证书开始的。如果您使用的是由ca签名的证书,那么两个应用程序(服务器和客户端)都需要能够验证另一方的整个链。它可以本地存储在某个存储中,也可以由另一方发送。链中至少有一个证书必须是最可信的(必须放入信任存储)。
有关ua安全工作原理的一般说明,请查看以下链接:https://opcfoundation.org/wp-content/uploads/2014/08/11_opc_ua_security_how_it_works.pdf
有关详细的帐户,请参阅github上提供的规范。
编辑:一个额外的评论在这里可能会有所帮助:你似乎正在使用一些sdk的目的有问题。虽然证书的验证(即进行签名检查等)通常包含在这样的sdk中,但应用程序的配置是应用程序(程序员)的任务。这包括存储可信证书的位置,以及在何处以及如何收集证书链中缺失的部分。您可能首先要检查客户机和服务器如何处理此任务,换句话说,通过尝试从UAMaven创建安全连接到OPC基金会的示例服务器,检查这些应用程序的配置任务。在OPC基金会的.NETSDK中,信任存储的位置默认为文件系统中的某个目录(子文件夹)
C:\ProgramData\OpcFoundation
,仅限windows)。但是,您可以在初始化验证器时覆盖它。其他客户端使用自己的目录结构来存储可信证书