我有一个架构表,其内容基本上可以归结为:

  • 一组用户
  • 一组的对象群体
  • 一个接入控制清单(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;

我的问题是,这是一个很好的方法吗?做这些建立临时看报表产生重大的开销,特别是相对于几个简单的查询?

此外,是否有办法使这些意见常在我的数据库定义,然后绑一个值的用户名称每届会议?这种方式,它没有创建所有这些意见用户每一次装载一页。

有帮助吗?

解决方案

几个问题与这样的方法:

  1. 一个用户 会议是不同的事情之一 数据库 会议。多个用户使用与排序的设置将会失败。

  2. 管理费用建立/摧毁的意见。

相反,我会建议如下看法:

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_)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top