mam schematu tabel, których zawartość w zasadzie sprowadzają się do:Korzystanie z widoków do kontroli dostępu w PostgreSQL
- Zestaw użytkowników
- Zestaw grup obiektów
- listę kontroli dostępu (ACL) wskazujące, co użytkownicy mają dostęp do grup, z których każdy należy do dokładnie jednej grupy.
Chcę utworzyć prostą aplikację, która obsługuje kontrolę dostępu. Myślę, że widoki byłyby tutaj dobrym podejściem.
Załóżmy, że mam następujący inicjalizacji bazy danych:
/* 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;
Mój pomysł jest użycie widoki, które odzwierciedlają bazy danych, ale ograniczają treści tylko to, co bieżący użytkownik (ustalona przez mojego skryptu PHP) mogą uzyskać dostęp (tutaj po prostu użyję użytkownika 'bob'). Załóżmy, że uruchomić to na początku każdej sesji PostgreSQL (czyli za każdym razem ktoś uzyskuje dostęp do strony na mojej stronie):
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;
Moje pytanie brzmi, czy jest to dobre podejście? Czy instrukcje CREATE TEMPORATION VIEW generują znaczny narzut, szczególnie w porównaniu z kilkoma prostymi zapytaniami?
Czy istnieje sposób na trwałe utrwalenie tych widoków w mojej definicji bazy danych, a następnie powiązanie wartości z nazwą użytkownika na sesję? W ten sposób nie trzeba tworzyć wszystkich tych widoków za każdym razem, gdy użytkownik ładuje stronę.
W odprawy dla update/delete, jeśli tylko odnoszą się do użytkownika o ID zamiast nazwy, nie mogę zrezygnować Utwórz widok AllowedUserGroup i odnośnik acl bezpośrednio dla tej części? –
Jasne, to zadziała dobrze. Możesz użyć AllowedUserGroup również dla SELECT, ale pomyślałem, że AllowedObjects będzie nieco bardziej użyteczne. Możesz również mieć AllowedObjects po prostu dołączyć 'objects' do AllowedUserGroup, więc cała logika ACL/Group/User jest zawarta w widoku AllowedUserGroup ... ścieżka wykonania powinna być taka sama w każdym kierunku. – richardtallent