Firebird - 如何枚举用户

Firebird - how to enumerate users

我们公司使用了更多使用 Firebird 数据库的应用程序。在某些安装中,我们使用安装在更多机器上的数据库服务。现在我正在尝试集中管理所有这些用户。为此,我正在编写新的应用程序。我需要的是连接到本地主机或网络中选定的 Firebird 服务并枚举所有用户。传统上 "gsec" 实用程序用于此目的。 "gsec" 是 Firebird 安装的一部分。我可以像这样使用此实用程序的命令行输出:

 user name                    uid   gid admin     full name
------------------------------------------------------------------------------------------------
SYSDBA                              0     0           Sql Server Administrator
TECHNICIAN                          0     0           Technician  Technician
TECHNIK                             0     0           Technik  Technik

但这对我来说似乎很麻烦。文本输出的格式也可以在下一个版本的 Firebird 中改变。所以我更愿意直接使用位于 fbclient.dll 库中的 Firebird api。此外,"gsec" 实用程序在内部使用 fbclient.dll,这可以在 SysInternals 的 ProcessExplorer 实用程序中看到。不幸的是,没有任何类型的文档。我所知道的是我应该在我的项目中包含 ibase.h 头文件。这个头文件的文档很少。我也下载了 "gsec" 实用程序的源代码,但它非常混乱。该项目无法在 Visual Studio 2008 中编译,因为缺少 fbclient.dll 的导入库。我尝试使用 these 指令生成导入库但失败了。

所以问题是:如何使用客户端库 fbclient.dll 枚举在 firebird 数据库机器中定义的用户?

您编写的不是 Firebird 版本。但是您可以使用服务 API (service_mgr) 获取用户列表等。检查 isc_action_svc_display_userisc_info_svc_get_users

使用 Firebird 3,您现在可以使用 SQL 查询用户。要查询用户,您需要是 SYSDBA 或具有 RDB$ADMIN 角色(否则您只能列出您自己的帐户),使用 SEC$USERS 虚拟 table:

select SEC$USER_NAME, SEC$FIRST_NAME, SEC$MIDDLE_NAME, SEC$LAST_NAME, 
       SEC$ACTIVE, SEC$ADMIN, SEC$DESCRIPTION, SEC$PLUGIN 
from SEC$USERS

早期用于管理用户的选项,例如使用服务 API(如下所述)或 gsec 现在已被弃用(请参阅 Firebird 3 发行说明中的​​ SQL Features for Managing Access)。

有此 API 的文档,请参阅 API 指南,它是 Interbase 6 文档集的一部分,可从 Firebird website 下载。较新的功能通常没有完整的文档记录,但获取用户信息 (isc_info_svc_get_users) 在过去 15 年中并没有太大变化。

API 指南的第 232 页专门记录了用户的检索(+ 第 221 页显示的一些代码):

char spb_buffer[6], *spb = spb_buffer;
char request_buffer[] = {
    isc_action_svc_display_user,
    isc_info_svc_get_users};
char result_buffer[1024], *p = result_buffer;
*spb++ = isc_info_svc_timeout;
ADD_SPB_NUMERIC(spb, 60); /* 1 minute timeout */

if (isc_service_query (
    status,
    &service_handle,
    NULL,
    spb - spb_buffer, spb_buffer,
    sizeof(request_buffer), request_buffer,
    sizeof(result_buffer), result_buffer))
{
    isc_print_status(status);
    isc_service_detach(status, &svc_handle);
    return;
}
do
{
    switch (*p++)
    {
    case isc_info_svc_get_users:
    {
        ISC_USHORT len, loop;
        ISC_ULONG id;
        char buffer[50], *buf = buffer;
        loop = (ISC_USHORT) isc_vax_integer (p, sizeof (ISC_USHORT));
        p += sizeof (ISC_USHORT);
        while (*p != isc_info_end)
        {
            switch (*p++)
            {
            case isc_spb_sec_username:
                len = (ISC_USHORT) isc_vax_integer(p, sizeof(ISC_USHORT));
                p += sizeof (ISC_USHORT);
                strncpy (buf, p, len);
                p += len;
                buffer[len] = 0;
                printf ("Username: %s\n", buffer);
                loop -= (len + sizeof(ISC_USHORT)+1);
                break;
            // Removed some information items for brevity
            case isc_spb_sec_groupid:
                id = isc_vax_integer (p, sizeof (ISC_ULONG));
                p += sizeof (ISC_ULONG);
                printf ("Group ID: %d\n", id);
                loop -= (len + sizeof(ISC_ULONG)+1);
                break;
            case isc_spb_sec_userid:
                id = isc_vax_integer (p, sizeof (ISC_ULONG));
                p += sizeof (ISC_ULONG);
                printf ("User ID: %d\n", id);
                loop -= (len + sizeof(ISC_ULONG)+1);
                break;
            default:
                *x = *p;
                break;
            } /* end switch */
        } /* end while */
        break;
    }
    // Other cases
}