我认为您正在混淆身份验证和授权。
我完全同意将安全模型保留在数据库中是明智的,尤其是在设计LedgerSMB时要考虑到多个客户端的访问。除非您计划使用中间件层进行3层迁移,否则将用户用作数据库角色是非常有意义的,尤其是对于会计应用程序而言。
但这并不意味着你必须进行身份验证使用PostgreSQL的支持的验证方法对数据库用户。您的数据库用户,角色和授予只能用于您的授权。
例如,这是如何用于Web ui的:
jane
连接到Web ui服务器并使用所需的任何方法进行身份验证,例如HTTPS X.509客户端证书握手和DIGEST身份验证。现在,服务器已接受来自用户的连接,该连接确实是jane
。
服务器使用固定的用户名/密码(或Kerberos或您喜欢的任何一种)连接到PostgreSQL,并以用户身份向db服务器进行身份验证webui
。db服务器信任webui
对用户的身份验证,因此webui
已被赋予适当GRANT
的权限(请参见下文)。
在该连接上,服务器SET ROLE jane;
用来承担用户的授权级别jane
。在运行RESET ROLE;
一个或另一个SET ROLE
运行之前,该连接将以jane
和SELECT current_user()
等将报告的相同访问权限运行jane
。
服务器维护其所拥有的数据库连接之间的关联SET ROLE
,以jane
和为用户的web会话jane
,不容许该通过与其他用户的其他连接,无需新的使用PostgreSQL的连接SET ROLE
其间。
您现在正在服务器外部进行身份验证,但仍在服务器中维护授权。Pg需要知道存在哪些用户,但不需要密码或身份验证方法。
看到:
细节
Webui服务器控制查询的运行,并且不会让jane
原始SQL运行(我希望!),因此jane
不能通过RESET ROLE; SET ROLE special_admin_user;
Web ui运行。为了增加安全性,我将向拒绝的服务器添加一个语句过滤器SET ROLE
,RESET ROLE
除非该连接位于或进入未分配的连接池中。
您仍然可以在其他客户端中对Pg使用直接身份验证;您可以自由地混合搭配。您只需要向用户授予可以通过Web登录GRANT
的webui
用户的权限SET ROLE
,然后为这些用户提供所需的任何常规CONNECT
权限,密码等。如果您希望将它们设置为仅用于Web,则REVOKE
它们CONNECT
对数据库的权限(以及从中获得的权限public
)。
为了使身份验证/授权的划分变得容易,我有一个特殊的角色assume_any_user
,GRANT
每个新创建的用户都应该扮演这个角色。然后GRANT assume_any_user
,我使用了受信任的Web前端之类的东西使用的真实用户名,从而赋予他们成为自己喜欢的任何用户的权利。
使是很重要的assume_any_user
一个NOINHERIT
角色,所以webui
用户或任何具有其自身没有privilges,只能对数据库的作用,一旦它SET ROLE
的真实用户。在任何情况下都不应webui
成为超级用户或数据库所有者。
如果您是连接池,则可以SET LOCAL ROLE
仅在事务中使用来设置角色,因此可以在COMMIT
或之后将连接返回到池ROLLBACK
。注意RESET ROLE
仍然可以使用,因此让客户端运行他们想要的任何SQL仍然是不安全的。
SET SESSION AUTHORIZATION
是此命令的相关版本,但功能更强大。它不需要角色成员身份,但这是一个仅限超级用户的命令。您不希望您的Web ui以超级用户身份连接。它可以被逆转RESET SESSION AUTHORIZATION
,SET SESSION AUTHORIZATION DEFAULT
或SET SESSION AUTHORIZATION theusername
重新获得超级用户权限,所以它不是一个特权坠安全屏障无论是。
SET SESSION AUTHORIZATION
如果您是角色成员但不是超级用户,那么像但一样工作但不可逆的命令就可以了。目前还没有,但如果您小心的话,仍然可以很好地将身份验证和授权分开。
范例与说明
CREATE ROLE dbowner NOLOGIN;
CREATE TABLE test_table(x text);
INSERT INTO test_table(x) VALUES ('bork');
ALTER TABLE test_table OWNER TO dbowner;
CREATE ROLE assume_any_user NOINHERIT NOLOGIN;
CREATE ROLE webui LOGIN PASSWORD 'somepw' IN ROLE assume_any_user;
CREATE ROLE jane LOGIN PASSWORD 'somepw';
GRANT jane TO assume_any_user;
GRANT ALL ON TABLE test_table TO jane;
CREATE ROLE jim LOGIN PASSWORD 'somepw';
GRANT jim TO assume_any_user;
现在连接为webui
。请注意,你不能做任何事情test_table
,但你可以 SET ROLE
到jane
和然后你可以访问test_table
:
$ psql -h 127.0.0.1 -U webui regress
Password for user webui:
regress=> SELECT session_user, current_user;
session_user | current_user
--------------+--------------
webui | webui
(1 row)
regress=> SELECT * FROM test_table;
ERROR: permission denied for relation test_table
regress=> SET ROLE jane;
SET
regress=> SELECT session_user, current_user;
session_user | current_user
--------------+--------------
webui | jane
(1 row)
regress=> SELECT * FROM test_table;
x
------
bork
(1 row)
需要注意的是webui
能 SET ROLE
到jim
,即使已经SET ROLE
d至jane
及,即使jane
没有被GRANT
编承担角色的权利jim
。SET ROLE
设置您的有效用户ID,但不会删除您SET ROLE
担任其他角色的能力,这是您连接的角色的属性,而不是当前的有效角色。因此,您必须仔细控制对SET ROLE
and RESET ROLE
命令的访问。SET ROLE
尽管确实很高兴,但AFAIK无法永久建立连接,真正成为目标用户。
比较:
$ psql -h 127.0.0.1 -U webui regress
Password for user webui:
regress=> SET ROLE jane;
SET
regress=> SET ROLE jim;
SET
regress=> SELECT session_user, current_user;
session_user | current_user
--------------+--------------
webui | jim
(1 row)
至:
$ psql -h 127.0.0.1 -U jane regress
Password for user jane:
regress=> SET ROLE webui;
ERROR: permission denied to set role "webui"
regress=> SET ROLE jim;
ERROR: permission denied to set role "jim"
这意味着SET ROLE
与以给定角色登录并不完全相同,您必须牢记这一点。
webui
不能做到SET ROLE
,dbowner
因为还没有做到GRANT
这一点:
regress=> SET ROLE dbowner;
ERROR: permission denied to set role "dbowner"
因此,就其自身而言,它几乎是无能为力的,它只能承担其他用户的权利,并且仅当这些用户启用了Web访问时才可以。