我是opc ua的新手,而不是java的专业人士。在java中设置客户端时,我在处理证书时遇到了麻烦。我想通过Basic 256,SignAndEncrypt连接到服务器。据我所知,在安全的这一阶段,客户端创建或加载的证书被发送到服务器,在那里它必须被接受。然后,服务器将证书发送回客户端,然后客户端需要接受证书。如果我错了请纠正我。
在客户端创建/加载证书并将其发送到服务器已经很好了(请参阅下面的代码),然后我可以在服务器端手动接受它。但在那之后,我陷入了困境:如何在代码中看到这个证书验证,如何找到服务器证书,更不用说接受它了?在实现过程中,我使用opc的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)lineOfCode是client.connect()。
提前感谢您的帮助!!
发布于 2017-07-14 15:23:41
服务器将向客户端发送它的证书。然后客户必须
(在服务器端,客户端证书也是如此)。
这是您从自签名证书开始的总结性。如果使用由CA签名的证书,则应用程序(服务器和客户端)都需要能够验证另一方的整个链。它可以在本地存储在某个商店中,也可以由另一方发送。链中至少有一个证书必须是最可靠的(必须放在信任存储中)。
有关UA安全工作的一般说明,请参阅以下链接:Works.pdf
如需详细说明,请参阅规范,可在GitHub上查阅。
编辑:这里可能有用的一个附加的注释:您似乎在使用某个SDK来解决这个问题。虽然证书的验证(即进行签名检查等)通常由这样的SDK负责,但应用程序的配置是应用程序(程序员)的任务。这包括存储受信任证书的位置,以及将丢失的证书链部分聚集在一起的位置和方式。您可能首先尝试检查演示客户端和服务器如何处理此任务,换句话说,通过尝试从例如UA专家创建一个从OPC基金会的示例服务器到示例服务器的安全连接,检查此类应用程序的配置任务。在OPC基础的.Net SDK中,信任存储的位置默认为文件系统中的某个目录( C:\ProgramData\OpcFoundation的一个子文件夹,它仅为C:\ProgramData\OpcFoundation)。但是,您可以在初始化验证器时覆盖它。其他客户端使用自己的目录结构来存储受信任的证书。
发布于 2017-07-21 13:39:35
显然,您指的是Prosys OPC UA Java SDK。
第一次尝试建立安全连接时,通常首先发生的情况是,服务器将拒绝对客户端应用程序的访问,并返回Bad_SecurityChecksFailed。
只有在您告诉服务器信任(客户端应用程序的证书)之后,您才会进入客户端应用程序尝试验证服务器证书的阶段--您的“validationListener”将被触发。
发布于 2017-07-28 13:19:17
谢谢大家的回答。同时,我尝试从Prosys示例中的connect()和initalize()方法中复制/粘贴并修改这些方法,这是可行的。我想这和更新一些信息有关,但我不太确定.事实上,我的应用程序现在正在工作,但感谢您的努力!
https://stackoverflow.com/questions/45103558
复制相似问题