open62541pp 0.15.0
C++ wrapper of open62541
Loading...
Searching...
No Matches
server_accesscontrol.cpp
#include <iostream>
using namespace opcua;
// Custom access control based on AccessControlDefault.
// If a user logs in with the username "admin", a session attribute "isAdmin" is stored. As an
// example, the user "admin" has write access level to the created variable node. So admins can
// change the value of the created variable node, anonymous users and the user "user" can't.
// Session attributes are available since open62541 v1.3, so this example requires at least v1.3.
class AccessControlCustom : public AccessControlDefault {
public:
using AccessControlDefault::AccessControlDefault; // inherit constructors
StatusCode activateSession(
Session& session,
const EndpointDescription& endpointDescription,
const ByteString& secureChannelRemoteCertificate,
const ExtensionObject& userIdentityToken
) override {
// Grant admin rights if user is logged in as "admin"
// Store attribute "isAdmin" as session attribute to use it in access callbacks
const auto* token = userIdentityToken.getDecodedData<UserNameIdentityToken>();
const bool isAdmin = (token != nullptr && token->getUserName() == "admin");
std::cout << "User has admin rights: " << isAdmin << std::endl;
session.setSessionAttribute({0, "isAdmin"}, Variant::fromScalar(isAdmin));
return AccessControlDefault::activateSession(
session, endpointDescription, secureChannelRemoteCertificate, userIdentityToken
);
}
Bitmask<AccessLevel> getUserAccessLevel(Session& session, const NodeId& nodeId) override {
const bool isAdmin = session.getSessionAttribute({0, "isAdmin"}).getScalar<bool>();
std::cout << "Get user access level of node id " << nodeId.toString() << std::endl;
std::cout << "Admin rights granted: " << isAdmin << std::endl;
return isAdmin
? AccessLevel::CurrentRead | AccessLevel::CurrentWrite
: AccessLevel::CurrentRead;
}
};
int main() {
// Exchanging usernames/passwords without encryption as plain text is dangerous.
// We are doing this just for demonstration, don't use it in production!
Server server;
AccessControlCustom accessControl(
true, // allow anonymous
{
{"admin", "admin"},
{"user", "user"},
}
);
server.setAccessControl(accessControl);
// Add variable node. Try to change its value as a client with different logins.
Node(server, ObjectId::ObjectsFolder)
{1, 1000},
"Variable",
.setAccessLevel(AccessLevel::CurrentRead | AccessLevel::CurrentWrite)
.setDataType(DataTypeId::Int32)
.setValueRank(ValueRank::Scalar)
.setValueScalar(0)
);
server.run();
}
Bitmask using (scoped) enums.
Definition bitmask.hpp:125
UA_ByteString wrapper class.
Definition types.hpp:490
UA_EndpointDescription wrapper class.
UA_ExtensionObject wrapper class.
Definition types.hpp:1664
T * getDecodedData() noexcept
Get pointer to the decoded data with given template type.
Definition types.hpp:1764
UA_NodeId wrapper class.
Definition types.hpp:590
std::string toString() const
Encode NodeId as a string like ns=1;s=SomeNode.
High-level node class to access node attribute, browse and populate address space.
Definition server.hpp:27
Node addVariable(const NodeId &id, std::string_view browseName, const VariableAttributes &attributes={}, const NodeId &variableType=VariableTypeId::BaseDataVariableType, const NodeId &referenceType=ReferenceTypeId::HasComponent)
Add variable.
Definition node.hpp:102
High-level server class.
Definition server.hpp:63
void run()
Run the server's main loop. This method will block until Server::stop is called.
void setAccessControl(AccessControlBase &accessControl)
Set custom access control.
High-level session class to manage client sessions.
Definition session.hpp:20
void setSessionAttribute(const QualifiedName &key, const Variant &value)
Attach a session attribute as a key-value pair.
Variant getSessionAttribute(const QualifiedName &key)
Get a session attribute by its key.
UA_StatusCode wrapper class.
Definition types.hpp:44
UA_UserNameIdentityToken wrapper class.
UA_VariableAttributes wrapper class.
auto & setAccessLevel(Bitmask< AccessLevel > accessLevel) noexcept