2017-07-14 436 views
2

我是新来的opc ua而不是java的专业版。在java中设置客户端时,我遇到了处理证书的问题。我想通过Basic 256,SignAndEncrypt连接到服务器。据我所知,在这个安全阶段,由客户创建或加载的证书被发送到服务器,在那里它必须被接受。然后服务器将证书发送回客户端,然后客户端需要接受该证书。请纠正我,如果我错了。如何从opc ua服务器接受/查找证书?

在客户端创建/加载证书并将其发送到服务器已经正常工作(请参阅下面的代码),然后我可以手动在服务器端接受它。但之后,我卡住了:如何在代码中看到此证书验证,以及如何找到服务器证书,更不用说接受它了? 在实现过程中,我使用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; 

初始化之后,我尝试这样的连接(与注释,我所想象的连接可以正常工作):

并引发错误:

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) 

随着lineOfCodeclient.connect()

在此先感谢您的帮助!

回答

1

服务器会将其证书发送给客户端。然后客户端必须

  1. 验证的有效性的证书。这相当于验证证书的签名,检查证书的有效性,证书中的主机名是否与端点中的主机名匹配,检查CRL等等。通常SDK(验证器)应该为您做这件事,但您可能需要将一些参数提供给验证器,这些验证器应该实际执行检查。当然,安全策略Basic256对证书应该符合的证书施加一些最低要求。您可以在这里查看要求:http://opcfoundation-onlineapplications.org/profilereporting/ - 转到安全类别 - >构面 - >安全策略。
  2. 检查服务器证书是否可信。这通常相当于检查(puclic密钥)证书的副本是否已放入某个选定为信任存储的证书存储区。如果您编写客户端,由您决定选择哪个商店,但您需要告诉验证器在哪里寻找。我不太了解Java中的OPc UA开发,但您应该检查验证器期望存储哪些证书。也许有一个默认的密钥文件。

(在服务器端,客户端证书也是如此)。

这就是你开始使用自签名证书的原因。如果您使用的是由CA签署的证书,则应用程序(服务器和客户端)都需要能够验证对方的整个链。它可以存储在本地某个商店或可以由另一方发送。链中至少有一个证书必须是trustest(必须放入信任存储区)。

有关UA安全的工作方式看看这个链接的一般描述: https://opcfoundation.org/wp-content/uploads/2014/08/11_OPC_UA_Security_How_It_Works.pdf

,你应该阅读说明书,可以在GitHub上详细说明。

编辑:一个附加说明可能有助于这里:你似乎正在使用一些SDK的目的有问题。虽然验证证书(即进行签名检查等)通常由这样的SDK覆盖,但应用程序的配置是应用程序(程序员)的任务。这包括存储可信证书的位置以及将证书链缺失部分收集在一起的位置和方式。您可能首先尝试检查演示客户端和服务器如何处理此任务,换句话说,通过尝试从UA Expert创建从OPC基金会到示例服务器的安全连接来检查此类应用程序的配置任务。在OPC基础的.Net SDK中,信任存储的位置默认为文件系统中的某个目录(C:\ProgramData\OpcFoundation的子文件夹,仅限于Windows)。但是,您可以在初始化验证器时覆盖它。其他客户使用自己的目录结构存储可信证书

+0

谢谢你的回答!我明白我必须处理服务器发送的证书。我的问题是更多的_programmatically_,因为我真的空白在这里:我已经设置了一个验证器(见上面的代码),当我通过'validator.getRejected/Revoked/TrustedCertificates'检查'client.connect()'之前和之后的证书。 length()'我在连接之前和之后都得到了'0'作为所有三种证书的答案。拒绝的目录中是否至少有一个? – Nanda

+0

@Nanda我对.Net基础案有更多的经验,但我期望在Java中有类似的方法。在Opc UA中,客户端必须信任服务器(我的答案中的第2步)。这通常通过将服务器证书放入特定位置来完成。这个位置必须让你的应用程序知道,这是你需要采取行动的地方(以编程方式)。您必须弄清楚如何告诉验证程序在哪里搜索(可信)证书。如果验证程序不提供这种属性,则需要以某种方式检查信任,但我不相信这一点。一个 – Thomas

+0

理由让我相信这是验证程序具有TrustedCertifcates属性。我希望应用程序能够在某些地方将某些商店的内容加载到该变量中。如果您调试此'TrustedCertificates'变量的初始化方式,您应该了解如何执行此操作的提示。 – Thomas

0

您显然是指Prosys OPC UA Java SDK

首先,当您尝试首次建立安全连接时,总是会发生以下情况:服务器拒绝访问您的客户端应用程序 - 并返回Bad_SecurityChecksFailed。

只有当您告诉服务器信任您的客户端应用程序的证书后,您是否会进入客户端应用程序将尝试验证服务器证书的阶段 - 并且您的“validationListener”将被触发。

0

谢谢大家的回答。与此同时,我尝试基本上复制/粘贴并修改Prosys SDK示例中SampleConsoleClient的connect()initalize()方法。猜猜它与更新某些信息有关,但我不太确定这一点......事实是,我的应用程序正在工作,但感谢您的努力!