如何根据请求者的id限制SQL列?

如何根据请求者的id限制SQL列?,sql,postgresql,Sql,Postgresql,在我的应用程序中,请求者只有查询特定列的权限。请求者之间的列可能不同。where子句在请求之间更改,因此返回的行随每个查询而更改。处理此访问控制的最佳方式是什么?我应该使用数组来存储允许的列,然后在应用程序中进行检查吗 我在使用PostgreSQL 9.x 例如: 我们有医疗专业人员可以访问患者记录,但并非所有医疗专业人员都应该能够访问所有信息。他们试图要求任何患者(有uid)的任意信息,但我们应该实施访问控制 所以说信息是姓名、出生日期、血型和疾病 医生A对所有领域都有权限 除了血型,B医生什

在我的应用程序中,请求者只有查询特定列的权限。请求者之间的列可能不同。where子句在请求之间更改,因此返回的行随每个查询而更改。处理此访问控制的最佳方式是什么?我应该使用数组来存储允许的列,然后在应用程序中进行检查吗

我在使用PostgreSQL 9.x

例如: 我们有医疗专业人员可以访问患者记录,但并非所有医疗专业人员都应该能够访问所有信息。他们试图要求任何患者(有uid)的任意信息,但我们应该实施访问控制

所以说信息是姓名、出生日期、血型和疾病

医生A对所有领域都有权限 除了血型,B医生什么都能看 管理员只能查看姓名和出生日期
血液学家只能查看血型

您可以采取两种方法:

  • 使用Postgres为每个用户(或用户角色)使用列级权限强制执行安全性。请在此处查看GRANT的语法:

  • 构建动态sql语句,限制每个用户可以返回哪些行。如果有许多用户,或者有许多不同的列组合,这可能会变得非常乏味。您可能希望保留一个用户ID表和“可选”表,以及用于构建查询语句的列名。如果希望将其推广到许多不同的查询,可以在执行列过滤的表返回函数的顶部构建它们,或者恢复到选项1


  • 对于选项1,确保联接中使用的列是可选择的…

    要实现选项2,我将有一个列权限表,如下所示:

    CREATE TABLE ColumnPerms
    (
        user_or_role      Varchar(50),
        table_name        Varchar(50),
        column_name       Varchar(50),
    )
    
    CREATE INDEX ix_Columnperms(user_or_role, table_name)
    
    *table_name*列允许在应用程序中的多个表上实现此功能:如果没有必要,请不要使用它。您可以采用角色名称以“@”字符开头的约定,以确保不会与用户名发生冲突

    现在,当您构建动态查询时,您可以执行以下操作

    SELECT column_name 
      FROM ColumnPerms 
     WHERE user_or_role = '@manager'
       AND table = 'Payroll'
       AND column_name IN ('first_name', 'last_name', 'hire_date', 'base_salary', 'bonus')
    
    (IN子句应包括可能返回的每一列)


    此查询的结果是允许用户查看的列名列表。在构建动态SQL时,只需遍历它来构建列列表。

    GRANT似乎是面向DB“用户”的,而我的“用户”是应用程序的用户。具体来说,一旦我打开与db的连接,我的应用程序的当前用户将被修复,我认为创建许多短期连接不是一个好主意。这将把选项减少到第2个。至于第二个选项,“可选”表的模式是什么?每行是否由每列的布尔值组成?我可以做应用程序方面的工作。我最初的建议是使用数组存储列并在应用程序中执行检查,这是不是考虑不周?这些列是用户在WHERE子句中可以拥有的,还是他们可以从查询中返回的,或者两者都有?无论哪种方式,我都会在db函数中尝试,输入参数是WHERE子句过滤器作为HSTORE,以及请求者的id(或您正在使用的任何内容)。在函数中,您可以按照选项2中的建议动态构造查询。我不认为编写一个db函数来进行过滤会有太多的工作,但更棘手的问题将是严格的测试,并使更改权限的列表保持最新。您的医疗数据示例是真实的吗?考虑到查询过滤器中的任何角落案例错误都可能将用户医疗数据暴露给不应该看到它的人,这似乎相当令人担忧。