【问题标题】:Seeking design recommendations for database server - client application寻求数据库服务器 - 客户端应用程序的设计建议
【发布时间】:2014-12-02 19:22:50
【问题描述】:

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

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

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

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

我已经想到了几种解决这一挑战的方法,但我正在寻求您关于最佳架构的建议,以防止用户在我的客户端应用程序之外访问数据库服务器。

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

  1. 编写我自己的服务器来维护允许连接到数据库服务器的用户列表。新的数据库用户只能使用这个“服务器”创建,用户的密码由两部分组成——第一部分是实际用户提供的密码,第二部分是随机生成的字符串,其副本存储在“服务器”。当用户登录我的“服务器”时,服务器将密码的第二部分提供给客户端,用户将提供密码的第一部分。这两个密码将连接起来并用于登录数据库服务器。这达到了预期的目标,因为用户的数据库密码与用户所知道的不同,因此如果不先向我的“服务器”查询密码的第二部分,就无法登录数据库服务器。

然而,这种设计对用户来说很麻烦——用户必须提供一个密码才能连接到我的“服务器”,然后再提供第二个密码才能连接到数据库服务器。在我的特殊情况下,数据库服务器上的数据也是加密的,这意味着用户必须提供第三个密码才能访问数据库。我认为这对于普通用户来说有点多。

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

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

【问题讨论】:

  • 为什么不使用 Postgres 的内置安全性?
  • 我很乐意。您能否更具体一些并推荐特定的功能?

标签: database-design architecture


【解决方案1】:

我们在 MS SQL Server 下遇到了一个非常相似的问题,并通过在存储过程级别提供“API”来解决它。希望您能够在 PostgreSQL 下做类似的事情。

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

公共和私有过程共同实现行级安全性和任何其他所需的业务逻辑。由于所有客户端都通过此 API “汇集”,因此没有人可以规避行级安全性或任何业务规则。这包括任何未来可能实现与现有数据库“对话”的应用程序。

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

您还应该考虑安全缓存。在我们的例子中,我们有一个非常复杂的安全机制,它支持权限继承(从父对象到子对象)和工作流,这使得计算成本很高——因此我们实现了一个安全缓存,它可以“延迟”更新并防止重复的安全计算。安全缓存完全隐藏在存储过程之后,对客户端透明。根据您的安全机制的复杂性,您可能会考虑某种安全缓存在性能方面是否是一个好主意...

【讨论】:

  • PostgreSQL 确实有存储过程。你的方法听起来很健壮,应该工作得很好。谢谢!
【解决方案2】:

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

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

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

目前,您需要通过表中的“所有者”列和阻止用户看到不应看到的行的视图来模拟行安全性。您需要弄清楚“共享”,可能使用 ACL 数组列(允许的角色),或者使用相关表。

9.3 有 security_barrier 视图,可以防止一些窥探。在 9.4 中,它们是可更新的。 9.4 还支持 WITH CHECK OPTION 视图,这在这里很有用。 9.4 应该会在本周晚些时候发布。

参见http://veil.projects.pgfoundry.org/curdocs/main.html

基本示例:

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}');

你显然需要添加一些其他的东西。

【讨论】:

  • 模仿行安全性几乎是我想要的。如果您更详细地描述您提出的方法,我将不胜感激。例如,您将如何实现与相关表的“共享”?
  • @CSLover 你愿意等9.4吗?
  • 当然可以。该应用程序的早期(现在功能失调)版本已实现,但我将从头开始,因此等待 9.4 完全没有问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多