使用的风景进行访问控制在PostgreSQL
-
22-09-2019 - |
题
我有一个架构表,其内容基本上可以归结为:
- 一组用户
- 一组的对象群体
- 一个接入控制清单(acl)表示的用户访问哪些组
- 一组的对象,每个都属于一个群组。
我想创建一个简单的应用程序,支持访问控制。我想景将是一个良好做法在这里。
假设我有以下数据库初始化:
/* Database definition */
BEGIN;
CREATE SCHEMA foo;
CREATE TABLE foo.users (
id SERIAL PRIMARY KEY,
name TEXT
);
CREATE TABLE foo.groups (
id SERIAL PRIMARY KEY,
name TEXT
);
CREATE TABLE foo.acl (
user_ INT REFERENCES foo.users,
group_ INT REFERENCES foo.groups
);
CREATE TABLE foo.objects (
id SERIAL PRIMARY KEY,
group_ INT REFERENCES foo.groups,
name TEXT,
data TEXT
);
/* Sample data */
-- Create groups A and B
INSERT INTO foo.groups VALUES (1, 'A');
INSERT INTO foo.groups VALUES (2, 'B');
-- Create objects belonging to group A
INSERT INTO foo.objects VALUES (1, 1, 'object in A', 'apples');
INSERT INTO foo.objects VALUES (2, 1, 'another object in A', 'asparagus');
-- Create objects belonging to group B
INSERT INTO foo.objects VALUES (3, 2, 'object in B', 'bananas');
INSERT INTO foo.objects VALUES (4, 2, 'object in B', 'blueberries');
-- Create users
INSERT INTO foo.users VALUES (1, 'alice');
INSERT INTO foo.users VALUES (2, 'amy');
INSERT INTO foo.users VALUES (3, 'billy');
INSERT INTO foo.users VALUES (4, 'bob');
INSERT INTO foo.users VALUES (5, 'caitlin');
INSERT INTO foo.users VALUES (6, 'charlie');
-- alice and amy can access group A
INSERT INTO foo.acl VALUES (1, 1);
INSERT INTO foo.acl VALUES (2, 1);
-- billy and bob can access group B
INSERT INTO foo.acl VALUES (3, 2);
INSERT INTO foo.acl VALUES (4, 2);
-- caitlin and charlie can access groups A and B
INSERT INTO foo.acl VALUES (5, 1);
INSERT INTO foo.acl VALUES (5, 2);
INSERT INTO foo.acl VALUES (6, 1);
INSERT INTO foo.acl VALUES (6, 2);
COMMIT;
我的想法是使用风景镜像的数据库,但是,限制的内容只有当前用户(确定我PHP script)的可访问(在这里我只会使用的用户'bob').假设我在开始的每一个PostgreSQL届会议(这意味着每一次个人访问网页上我的网站):
BEGIN;
CREATE TEMPORARY VIEW users AS
SELECT * FROM foo.users
WHERE name='bob';
CREATE TEMPORARY VIEW acl AS
SELECT acl.* FROM foo.acl, users
WHERE acl.user_=users.id;
CREATE TEMPORARY VIEW groups AS
SELECT groups.* FROM foo.groups, acl
WHERE groups.id=acl.group_;
CREATE TEMPORARY VIEW objects AS
SELECT objects.* FROM foo.objects, groups
WHERE objects.group_=groups.id;
COMMIT;
我的问题是,这是一个很好的方法吗?做这些建立临时看报表产生重大的开销,特别是相对于几个简单的查询?
此外,是否有办法使这些意见常在我的数据库定义,然后绑一个值的用户名称每届会议?这种方式,它没有创建所有这些意见用户每一次装载一页。
解决方案
几个问题与这样的方法:
一个用户 网 会议是不同的事情之一 数据库 会议。多个用户使用与排序的设置将会失败。
管理费用建立/摧毁的意见。
相反,我会建议如下看法:
CREATE VIEW AllowedObjects
SELECT objects.*, users.name AS alloweduser
FROM objects
INNER JOIN groups ON groups.id = objects.group_
INNER JOIN acl ON acl.group_ = groups.id
INNER JOIN users ON users.id = acl.user_
然后,无论你选择的对象:
SELECT * FROM AllowedObjects
WHERE alloweduser='Bob'
这假定鲍勃*只能有一个ACL加入他的一个特别小组,否则一个独特的将是必要的。
这可能是抽象到一个稍微不那么复杂认为,可以用来使它更易于检查的权限,更新和删除:
CREATE VIEW AllowedUserGroup
SELECT groups.id AS allowedgroup, users.name AS alloweduser
FROM groups
INNER JOIN acl ON acl.group_ = groups.id
INNER JOIN users ON users.id = acl.user_
这提供了一个平景的用户是在哪些群体,你可以检查对象表在UPDATE/DELETE:
UPDATE objects SET foo='bar' WHERE id=42 AND EXISTS
(SELECT NULL FROM AllowedUserGroup
WHERE alloweduser='Bob' AND allowedgroup = objects.group_)
不隶属于 StackOverflow