如何在 node-opcua 服务器中获取连接的客户端和客户端证书

How to get connected clients and client certificate in node-opcua server

我有一个 node-opcua 服务器设置,有 2 个客户端连接到它,安全模式设置为 SignAndEncrypt。现在,我有 2 个问题:

  1. 有没有办法让服务器知道有多少客户端连接到它?
  2. 服务器应用程序想知道连接的客户端的身份,是否有 API 来获取在 OpenSecureChannel 期间获得的客户端证书?

OPCUA Server可以在RootFolder.Server.ServerDiagnostics节点下暴露这些信息,您需要的信息应该可以通过OPCUA访问。

这个小的 node-opcua 客户端程序会告诉你怎么做。

注意:

  • 某些数据(例如安全诊断)需要安全连接和非匿名用户

client_extract_server_diagnostic.ts

// this script is typescript and can be run this way
// $ npx ts-node client_extract_server_diagnostic.ts

import { 
    AttributeIds,
    OPCUAClient,
    ClientSession, 
    StatusCodes,
    MessageSecurityMode,
    SecurityPolicy,
    UserIdentityInfoUserName,
    UserTokenType   
} from "node-opcua";

// the opcua server to connect to
const endpointUrl = "opc.tcp://localhost:48010";

// the credential 
const userIdentityToken: UserIdentityInfoUserName = {
    password: "secret",
    userName: "root",
    type: UserTokenType.UserName
};

async function extractServerStatistics(session: ClientSession) {

    const nodesToRead = [
        { 
            attributeIds: AttributeIds.Value, nodeId:"Server_ServerDiagnostics_EnabledFlag" 
        },
        { 
            attributeIds: AttributeIds.Value, nodeId:"Server_ServerDiagnostics_ServerDiagnosticsSummary_CurrentSessionCount" //i=2277 
        },
        {
            attributeIds: AttributeIds.Value, nodeId:"Server_ServerDiagnostics_ServerDiagnosticsSummary_CurrentSubscriptionCount" // i=2285 
        },
        {
            attributeIds: AttributeIds.Value, nodeId: "Server_ServerDiagnostics_ServerDiagnosticsSummary_CumulatedSessionCount" // i=2278 
        },
        {
            attributeIds: AttributeIds.Value, nodeId: "Server_ServerDiagnostics_ServerDiagnosticsSummary_CumulatedSubscriptionCount" // i=2278 
        },
        {
            attributeIds: AttributeIds.Value, nodeId: "Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionSecurityDiagnosticsArray" // i=3708 
        }

    ];
    const dataValues = await session.read(nodesToRead);

    console.log("Diagnostic enabled ?         = ", dataValues[0].value.value);
    console.log("Current Session Count        = ", dataValues[1].value.value);
    console.log("Current Subscription Count   = ", dataValues[2].value.value);
    console.log("Cumulated Session Count      = ", dataValues[3].value.value);
    console.log("Cumulated Subscription Count = ", dataValues[4].value.value);

    // note reading SessionSecurityDiagnotiscArray may requires authenticated session to succeed
    console.log("SessionSecurityDiagnotiscArray       = ");

    if (dataValues[5].statusCode === StatusCodes.Good) {
        const sessionSecurityDiagnosticArray = dataValues[5].value.value;
        // console.log(dataValues[5].value.value.toString());
        for (const sessionSecurityDiagnostic of sessionSecurityDiagnosticArray)  {
            console.log(" session client certificate ", sessionSecurityDiagnostic.clientCertificate.toString("base64"));
            console.log();
        }
    } else {
        console.log(dataValues[5].toString());
    }
}
( async () => {

    try {
        const client = OPCUAClient.create({
            endpoint_must_exist: false,
            securityMode: MessageSecurityMode.SignAndEncrypt,
            securityPolicy: SecurityPolicy.Basic256Sha256,

        });
        client.on("backoff",() => console.log("still trying to connec to ", endpointUrl));

        await client.connect(endpointUrl);

        const session = await client.createSession(userIdentityToken);

        await extractServerStatistics(session);

        await session.close();
        await client.disconnect();
        console.log("done");
    } catch(err) {
        console.log("Err" , err.message);
        process.exit(1);
    }
})();