Database design 寻求数据库服务器-客户端应用程序的设计建议

Database design 寻求数据库服务器-客户端应用程序的设计建议,database-design,architecture,Database Design,Architecture,我正在开发一个带有PostgreSQL数据库后端的文件管理系统。我正在使用Qt库编写客户端,它将连接和查询数据库服务器 默认情况下,文件管理系统限制所有用户访问顶级目录,除非特定用户可以访问特定的顶级目录。任何人都可以向任何人授予访问权,只要授予访问权的用户已经拥有访问权。这是通过在数据库中使用两个外键维护一个表来实现的:userID_fk和directoryID_fk。如果此表中存在一条记录,且某个特定用户有权访问某个特定目录,则该目录将显示在用户屏幕上。否则,该目录对用户不可见 这种设计带来

我正在开发一个带有PostgreSQL数据库后端的文件管理系统。我正在使用Qt库编写客户端,它将连接和查询数据库服务器

默认情况下,文件管理系统限制所有用户访问顶级目录,除非特定用户可以访问特定的顶级目录。任何人都可以向任何人授予访问权,只要授予访问权的用户已经拥有访问权。这是通过在数据库中使用两个外键维护一个表来实现的:userID_fk和directoryID_fk。如果此表中存在一条记录,且某个特定用户有权访问某个特定目录,则该目录将显示在用户屏幕上。否则,该目录对用户不可见

这种设计带来了一个挑战:用户已经能够连接到数据库,并且就数据库服务器而言,用户是合法用户,因此没有访问某个目录的权限的用户很容易通过简单地连接到数据库服务器而不使用我的客户端应用程序来授予自己访问权限,只需在表中添加一条记录,其中包含目录id和他们自己的用户id。但是,我不允许这样做

我想要实现的是让所有数据库用户都能完全访问数据库服务器,但只能通过我自己的客户机应用程序,而不能在它之外

我已经想到了几种解决这一难题的方法,但我正在寻求您的建议,以确定防止用户在我的客户机应用程序之外访问数据库服务器的最佳体系结构

我想到的可能的设计方法:

  • 编写我自己的服务器,该服务器将维护允许连接到数据库服务器的用户列表。新的数据库用户将仅使用此“服务器”创建,用户密码由两部分组成-第一部分为实际用户提供的密码,第二部分为随机生成的字符串,其副本存储在“服务器”上。当用户登录到我的“服务器”时,服务器将向客户端提供第二部分密码,用户将提供第一部分密码。这两个密码将连接起来并用于登录数据库服务器。这实现了预期的目标,因为用户的数据库密码与用户知道的不同,因此在未首先查询我的“服务器”以获取密码的第二部分之前,无法登录到数据库服务器
  • 然而,这种设计对用户来说很麻烦——用户必须提供一个密码来连接到我的“服务器”,然后提供第二个密码来连接到数据库服务器。在我的例子中,数据库服务器上的数据也是加密的,这意味着用户必须提供第三个密码才能访问数据库。我认为这对于普通用户来说有点过分

  • 另一种设计是编写自己的服务器,为客户端提供所有功能。因此,客户机只查询我的“服务器”,然后查询真正的数据库服务器。从客户端的角度来看,这提供了一种更干净的方法,因为只需要提供2个密码,但编程起来要困难得多,我将重新发明轮子,因为数据库服务器已经具有非常快速和可靠的优秀多用户并发访问。我的服务器会增加额外的复杂性,可能会显著降低速度,因此可能不是一种实用的方法

  • 除了这两种方法之外,我还没有想到更好的设计。我真的很感激你的建议,包括你对我提议的设计的想法。非常感谢。

    我认为你最好使用Postgres内置的安全系统,而不是自己编写

    每个用户都有自己的用户名/密码(也可以使用SSL证书或Kerberos)

    Postgres支持用户和角色,对表、模式等的访问控制,以及列安全性

    目前,您需要使用表中的“owner”列和视图来模拟行安全性,这些视图阻止用户看到他们不应该看到的行。您需要了解“共享”,可能是使用ACL数组列(允许的角色)或使用相关表

    9.3具有安全屏障视图,可防止一些窥探。在9.4中,它们是可更新的。9.4还支持复选选项视图,这在这里很有用。9.4应该在本周晚些时候发布

    我也看到了

    基本示例:

    create schema data;
    
    create table data.files (
      file_id int primary key,
      name text not null,
      owner name not null default current_user, --use a trigger in real world
      acl name[] null
    );
    
    create view files as 
      select
        *
      from data.files
      where 
        owner = current_user
        or acl && array[current_user]; --&& is array overlap operator
    
    insert into data.files values (1, 'test', 'admin', '{CSLover}');
    

    显然,您需要添加一些其他内容。

    我们在MS SQL Server下遇到了一个非常类似的问题,通过在存储过程级别提供“API”解决了这个问题。希望您能够在PostgreSQL下执行类似的操作

    其思想是禁止所有客户端直接查询数据库。相反,您只对“公共”存储过程授予“执行”权限。外部客户端完全无法访问“私有”过程(即实施细节)和表

    公共和私有过程一起实现行级安全性和任何其他所需的业务逻辑。由于所有客户机都是通过这个API“漏斗式”的,所以没有人能够绕过行级安全或任何业务规则。这包括将来可能实现的与现有数据库“对话”的任何应用程序

    在我们的例子中,我们在数据库用户和“应用程序用户”之间有1:1的映射,只需让DBMS在登录期间对用户进行身份验证(这也有一个与Active Directory集成的额外好处,这在我们的例子中很重要)。然后,存储过程将使用当前数据库用户名来实现行级安全性

    你也应该考虑安全缓存。在我们的例子中,我们有一个非常复杂的安全机制,支持权限继承(从父对象到子对象)和工作流,这