让我们创建一个用户和包含一些数据的表:
CREATE ROLE admin;
CREATE TABLE employee (empno int, ename text, address text, salary int, account_number text);
INSERT INTO employee VALUES
(1, 'john' , '2 down str' , 20000, 'HDFC-22001')
, (2, 'clark' , '132 south avn', 80000, 'HDFC-23029')
, (3, 'soojie', 'Down st 17th' , 60000, 'ICICI-19022')
;
现在,让我们创建列级权限:
postgres=> \c postgres edb
You are now connected to database "postgres" as user "edb".
postgres=# grant select (empno, ename, address) on employee to admin;
GRANT
postgres=# \c postgres admin
You are now connected to database "postgres" as user "admin".
postgres=> select empno, ename, address, salary from employee;
ERROR: permission denied for table employee
postgres=> select empno, ename, address from employee;
empno | ename | address
-------+--------+---------------
1 | john | 2 down str
2 | clark | 132 south avn
3 | soojie | Down st 17th
到目前为止一切正常。
但是在 PostgreSQL 中是否可以创建更复杂的规则——而不是完全限制
admin
用户查看 salary
列,例如,返回所有行的 NULL
值并显示实际值仅工资栏,例如,ename = 'clark'
?
换句话说,不要像下面的示例那样返回错误:
postgres=> select empno, ename, address, salary from employee;
ERROR: permission denied for table employee
返回如下结果:
empno | ename | address | salary
-------+--------+---------------+--------
1 | john | 2 down str | NULL
2 | clark | 132 south avn | 80000
3 | soojie | Down st 17th | NULL
这很可能可以通过视图来完成,但我对使用如上所示的简单规则实现此结果特别感兴趣。
如果可能的话,我希望能举个例子。
正确的方法是视图:
CREATE VIEW emp_view WITH (security_barrier = on) AS
SELECT empno, ename, address,
CASE WHEN ename = 'clark'
THEN salary
END AS salary
FROM employee;
GRANT SELECT ON emp_view TO admin;
然后
admin
就可以看到你想要的数据,而无需直接访问底层表。
security_barrier
对于防止 admin
访问她不应该看到的数据是必要的。有关详细信息,请参阅文档。