Eclipse Milo、UaExpert:没有匹配会话安全设置的端点
Eclipse Milo, UaExpert: no endpoint matching the session security settings
我想用 UaExpert 测试一个简单的 OPC-UA 服务器。服务器已启动,当我尝试使用 UaExpert 连接服务器时,我不断收到以下消息
18:18:48.633 | Server Node | test | Endpoint: 'opc.tcp://DESKTOP-ss:12686/test'
18:18:48.633 | Server Node | test | Security policy: 'http://opcfoundation.org/UA/SecurityPolicy#None'
18:18:48.633 | Server Node | test | ApplicationUri: 'com:test'
18:18:48.633 | Server Node | test | Used UserTokenType: Anonymous
18:18:48.633 | Server Node | test | The server returned no certificate, all certificate checks will be skipped.
18:18:48.664 | General | | Error: UaSessionPrivate::activateSession - no endpoint matching the session security settings
18:18:48.664 | Server Node | test | Error 'BadConfigurationError' was returned during ActivateSession
18:18:48.664 | Server Node | test | Connection status of server 'test' changed to 'Disconnected'.
我正在使用提供的 ExampleServer,并连接到没有安全和匿名策略的服务器。
有人可以帮忙吗?
编辑 - 2018 年 1 月 12 日
我的代码如下:
OPCUA接口Class
public class OPCUAInterface {
private static final String OPCUA_APP_URI = "com:test";
private final OpcUaServer server;
public static void main(String[] args) throws Exception {
OPCUAInterface server = new OPCUAInterface();
server.startup().get();
final CompletableFuture<Void> future = new CompletableFuture<>();
Runtime.getRuntime().addShutdownHook(new Thread(() -> future.complete(null)));
future.get();
}
public OPCUAInterface() throws Exception {
File securityTempDir = new File(System.getProperty("java.io.tmpdir"), "security");
if (!securityTempDir.exists() && !securityTempDir.mkdirs()) {
throw new Exception("unable to create security temp dir: " + securityTempDir);
}
LoggerFactory.getLogger(getClass()).info("security temp dir: {}", securityTempDir.getAbsolutePath());
// KeyStoreLoader loader = new KeyStoreLoader().load(securityTempDir);
DefaultCertificateManager certificateManager = new DefaultCertificateManager(
// loader.getServerKeyPair(),
// loader.getServerCertificateChain()
);
File pkiDir = securityTempDir.toPath().resolve("pki").toFile();
DirectoryCertificateValidator certificateValidator = new DirectoryCertificateValidator(pkiDir);
UsernameIdentityValidator identityValidator = new UsernameIdentityValidator(
true,
authChallenge -> {
String username = authChallenge.getUsername();
String password = authChallenge.getPassword();
boolean userOk = "test".equals(username) && "test".equals(password);
boolean adminOk = "admin".equals(username) && "password2".equals(password);
return userOk || adminOk;
}
);
X509IdentityValidator x509IdentityValidator = new X509IdentityValidator(c -> true);
List<String> bindAddresses = new ArrayList<>();
bindAddresses.add("0.0.0.0");
List<String> endpointAddresses = new ArrayList<>();
endpointAddresses.add(HostnameUtil.getHostname());
endpointAddresses.addAll(HostnameUtil.getHostnames("0.0.0.0"));
String applicationUri = OPCUA_APP_URI;
OpcUaServerConfig serverConfig = OpcUaServerConfig.builder()
.setApplicationUri(applicationUri)
.setApplicationName(LocalizedText.english("test program"))
.setBindPort(62547)
.setBindAddresses(bindAddresses)
.setEndpointAddresses(endpointAddresses)
.setBuildInfo(
new BuildInfo(
applicationUri,
"test",
"test program",
OpcUaServer.SDK_VERSION,
"0.1", DateTime.now()))
.setCertificateManager(certificateManager)
.setCertificateValidator(certificateValidator)
.setIdentityValidator(new CompositeValidator(identityValidator, x509IdentityValidator,
AnonymousIdentityValidator.INSTANCE))
.setProductUri(applicationUri)
.setServerName("test")
.setSecurityPolicies(
EnumSet.of(
SecurityPolicy.None,
SecurityPolicy.Basic128Rsa15,
SecurityPolicy.Basic256,
SecurityPolicy.Basic256Sha256,
SecurityPolicy.Aes128_Sha256_RsaOaep,
SecurityPolicy.Aes256_Sha256_RsaPss
))
.setUserTokenPolicies(
ImmutableList.of(
USER_TOKEN_POLICY_ANONYMOUS,
USER_TOKEN_POLICY_USERNAME,
USER_TOKEN_POLICY_X509
))
.build();
server = new OpcUaServer(serverConfig);
server.getNamespaceManager().registerAndAdd(
TestNameSpace.NAMESPACE_URI,
idx -> new TestNameSpace(server, idx));
}
public OpcUaServer getServer() {
return server;
}
public CompletableFuture<OpcUaServer> startup() {
return server.startup();
}
public CompletableFuture<OpcUaServer> shutdown() {
return server.shutdown();
}
}
测试名称空间Class
public class TestNameSpace implements Namespace {
final static Logger logger = LogManager.getLogger(TestNameSpace.class);
public static final String NAMESPACE_URI = "com:test:mytest";
private OpcUaServer server;
private UShort namespaceIndex;
private SubscriptionModel subscriptionModel;
private NodeFactory nodeFactory;
public TestNameSpace(OpcUaServer server, UShort namespaceIndex) {
this.server = server;
this.namespaceIndex = namespaceIndex;
subscriptionModel = new SubscriptionModel(server, this);
nodeFactory = new NodeFactory(
server.getNodeMap(),
server.getObjectTypeManager(),
server.getVariableTypeManager()
);
try {
NodeId folderNodeId = new NodeId(namespaceIndex, "test");
UaFolderNode folderNode = new UaFolderNode(
server.getNodeMap(),
folderNodeId,
new QualifiedName(namespaceIndex, "test"),
LocalizedText.english("test")
);
server.getNodeMap().addNode(folderNode);
// Make sure our new folder shows up under the server's Objects folder
server.getUaNamespace().addReference(
Identifiers.ObjectsFolder,
Identifiers.Organizes,
true,
folderNodeId.expanded(),
NodeClass.Object
);
} catch (UaException e) {
logger.error("Error loading nodes: " + e.getMessage() + " " + e);
}
}
@Override
public void read(ReadContext context, Double maxAge, TimestampsToReturn timestamps, List<ReadValueId> readValueIds) {
// TODO Auto-generated method stub
}
@Override
public void write(WriteContext context, List<WriteValue> writeValues) {
// TODO Auto-generated method stub
}
@Override
public void onDataItemsCreated(List<DataItem> dataItems) {
// TODO Auto-generated method stub
}
@Override
public void onDataItemsModified(List<DataItem> dataItems) {
// TODO Auto-generated method stub
}
@Override
public void onDataItemsDeleted(List<DataItem> dataItems) {
// TODO Auto-generated method stub
}
@Override
public void onMonitoringModeChanged(List<MonitoredItem> monitoredItems) {
// TODO Auto-generated method stub
}
@Override
public CompletableFuture<List<Reference>> browse(AccessContext context, NodeId nodeId) {
ServerNode node = server.getNodeMap().get(nodeId);
if (node != null) {
return CompletableFuture.completedFuture(node.getReferences());
} else {
return FutureUtils.failedFuture(new UaException(StatusCodes.Bad_NodeIdUnknown));
}
}
@Override
public UShort getNamespaceIndex() {
// TODO Auto-generated method stub
return namespaceIndex;
}
@Override
public String getNamespaceUri() {
// TODO Auto-generated method stub
return NAMESPACE_URI;
}
}
我无法复制您所看到的确切问题。使用未修改的示例服务器和命名空间 UaExpert 连接没有问题。
使用您的代码会出现一堆超时错误,因为您的命名空间实现不完整。
我想用 UaExpert 测试一个简单的 OPC-UA 服务器。服务器已启动,当我尝试使用 UaExpert 连接服务器时,我不断收到以下消息
18:18:48.633 | Server Node | test | Endpoint: 'opc.tcp://DESKTOP-ss:12686/test'
18:18:48.633 | Server Node | test | Security policy: 'http://opcfoundation.org/UA/SecurityPolicy#None'
18:18:48.633 | Server Node | test | ApplicationUri: 'com:test'
18:18:48.633 | Server Node | test | Used UserTokenType: Anonymous
18:18:48.633 | Server Node | test | The server returned no certificate, all certificate checks will be skipped.
18:18:48.664 | General | | Error: UaSessionPrivate::activateSession - no endpoint matching the session security settings
18:18:48.664 | Server Node | test | Error 'BadConfigurationError' was returned during ActivateSession
18:18:48.664 | Server Node | test | Connection status of server 'test' changed to 'Disconnected'.
我正在使用提供的 ExampleServer,并连接到没有安全和匿名策略的服务器。
有人可以帮忙吗?
编辑 - 2018 年 1 月 12 日
我的代码如下:
OPCUA接口Class
public class OPCUAInterface {
private static final String OPCUA_APP_URI = "com:test";
private final OpcUaServer server;
public static void main(String[] args) throws Exception {
OPCUAInterface server = new OPCUAInterface();
server.startup().get();
final CompletableFuture<Void> future = new CompletableFuture<>();
Runtime.getRuntime().addShutdownHook(new Thread(() -> future.complete(null)));
future.get();
}
public OPCUAInterface() throws Exception {
File securityTempDir = new File(System.getProperty("java.io.tmpdir"), "security");
if (!securityTempDir.exists() && !securityTempDir.mkdirs()) {
throw new Exception("unable to create security temp dir: " + securityTempDir);
}
LoggerFactory.getLogger(getClass()).info("security temp dir: {}", securityTempDir.getAbsolutePath());
// KeyStoreLoader loader = new KeyStoreLoader().load(securityTempDir);
DefaultCertificateManager certificateManager = new DefaultCertificateManager(
// loader.getServerKeyPair(),
// loader.getServerCertificateChain()
);
File pkiDir = securityTempDir.toPath().resolve("pki").toFile();
DirectoryCertificateValidator certificateValidator = new DirectoryCertificateValidator(pkiDir);
UsernameIdentityValidator identityValidator = new UsernameIdentityValidator(
true,
authChallenge -> {
String username = authChallenge.getUsername();
String password = authChallenge.getPassword();
boolean userOk = "test".equals(username) && "test".equals(password);
boolean adminOk = "admin".equals(username) && "password2".equals(password);
return userOk || adminOk;
}
);
X509IdentityValidator x509IdentityValidator = new X509IdentityValidator(c -> true);
List<String> bindAddresses = new ArrayList<>();
bindAddresses.add("0.0.0.0");
List<String> endpointAddresses = new ArrayList<>();
endpointAddresses.add(HostnameUtil.getHostname());
endpointAddresses.addAll(HostnameUtil.getHostnames("0.0.0.0"));
String applicationUri = OPCUA_APP_URI;
OpcUaServerConfig serverConfig = OpcUaServerConfig.builder()
.setApplicationUri(applicationUri)
.setApplicationName(LocalizedText.english("test program"))
.setBindPort(62547)
.setBindAddresses(bindAddresses)
.setEndpointAddresses(endpointAddresses)
.setBuildInfo(
new BuildInfo(
applicationUri,
"test",
"test program",
OpcUaServer.SDK_VERSION,
"0.1", DateTime.now()))
.setCertificateManager(certificateManager)
.setCertificateValidator(certificateValidator)
.setIdentityValidator(new CompositeValidator(identityValidator, x509IdentityValidator,
AnonymousIdentityValidator.INSTANCE))
.setProductUri(applicationUri)
.setServerName("test")
.setSecurityPolicies(
EnumSet.of(
SecurityPolicy.None,
SecurityPolicy.Basic128Rsa15,
SecurityPolicy.Basic256,
SecurityPolicy.Basic256Sha256,
SecurityPolicy.Aes128_Sha256_RsaOaep,
SecurityPolicy.Aes256_Sha256_RsaPss
))
.setUserTokenPolicies(
ImmutableList.of(
USER_TOKEN_POLICY_ANONYMOUS,
USER_TOKEN_POLICY_USERNAME,
USER_TOKEN_POLICY_X509
))
.build();
server = new OpcUaServer(serverConfig);
server.getNamespaceManager().registerAndAdd(
TestNameSpace.NAMESPACE_URI,
idx -> new TestNameSpace(server, idx));
}
public OpcUaServer getServer() {
return server;
}
public CompletableFuture<OpcUaServer> startup() {
return server.startup();
}
public CompletableFuture<OpcUaServer> shutdown() {
return server.shutdown();
}
}
测试名称空间Class
public class TestNameSpace implements Namespace {
final static Logger logger = LogManager.getLogger(TestNameSpace.class);
public static final String NAMESPACE_URI = "com:test:mytest";
private OpcUaServer server;
private UShort namespaceIndex;
private SubscriptionModel subscriptionModel;
private NodeFactory nodeFactory;
public TestNameSpace(OpcUaServer server, UShort namespaceIndex) {
this.server = server;
this.namespaceIndex = namespaceIndex;
subscriptionModel = new SubscriptionModel(server, this);
nodeFactory = new NodeFactory(
server.getNodeMap(),
server.getObjectTypeManager(),
server.getVariableTypeManager()
);
try {
NodeId folderNodeId = new NodeId(namespaceIndex, "test");
UaFolderNode folderNode = new UaFolderNode(
server.getNodeMap(),
folderNodeId,
new QualifiedName(namespaceIndex, "test"),
LocalizedText.english("test")
);
server.getNodeMap().addNode(folderNode);
// Make sure our new folder shows up under the server's Objects folder
server.getUaNamespace().addReference(
Identifiers.ObjectsFolder,
Identifiers.Organizes,
true,
folderNodeId.expanded(),
NodeClass.Object
);
} catch (UaException e) {
logger.error("Error loading nodes: " + e.getMessage() + " " + e);
}
}
@Override
public void read(ReadContext context, Double maxAge, TimestampsToReturn timestamps, List<ReadValueId> readValueIds) {
// TODO Auto-generated method stub
}
@Override
public void write(WriteContext context, List<WriteValue> writeValues) {
// TODO Auto-generated method stub
}
@Override
public void onDataItemsCreated(List<DataItem> dataItems) {
// TODO Auto-generated method stub
}
@Override
public void onDataItemsModified(List<DataItem> dataItems) {
// TODO Auto-generated method stub
}
@Override
public void onDataItemsDeleted(List<DataItem> dataItems) {
// TODO Auto-generated method stub
}
@Override
public void onMonitoringModeChanged(List<MonitoredItem> monitoredItems) {
// TODO Auto-generated method stub
}
@Override
public CompletableFuture<List<Reference>> browse(AccessContext context, NodeId nodeId) {
ServerNode node = server.getNodeMap().get(nodeId);
if (node != null) {
return CompletableFuture.completedFuture(node.getReferences());
} else {
return FutureUtils.failedFuture(new UaException(StatusCodes.Bad_NodeIdUnknown));
}
}
@Override
public UShort getNamespaceIndex() {
// TODO Auto-generated method stub
return namespaceIndex;
}
@Override
public String getNamespaceUri() {
// TODO Auto-generated method stub
return NAMESPACE_URI;
}
}
我无法复制您所看到的确切问题。使用未修改的示例服务器和命名空间 UaExpert 连接没有问题。
使用您的代码会出现一堆超时错误,因为您的命名空间实现不完整。