Entwicklung des Themas und fĂŒr eine umfassende Antwort auf
Die verwendete Strategie basiert auf dem Konzept "Business-Logik in der Datenbank", was hier etwas ausfĂŒhrlicher beschrieben wurde -
Der theoretische Teil ist in der Dokumentation hervorragend beschrieben â . Im Folgenden wird die praktische Umsetzung einer spezifischen GeschĂ€ftsanforderung - das rollenbasierte Zugriffsmodell - behandelt.

Der Artikel enthĂ€lt nichts Neues, es gibt keine versteckte Bedeutung oder geheimes Wissen. Es ist einfach eine Skizze zur praktischen Umsetzung einer theoretischen Idee. Wer interessiert ist â lesen Sie. Wer nicht interessiert ist â verschwenden Sie nicht Ihre Zeit.
Aufgabenstellung
Es ist notwendig, den Zugriff auf das Anzeigen / EinfĂŒgen / Ăndern / Löschen von Dokumenten entsprechend der Rolle des Benutzers der Anwendung zu unterscheiden. Unter einer Rolle wird ein Eintrag in der Tabelle verstanden roles die durch eine viele-zu-viele Beziehung mit der Tabelle verbunden ist. users. Die Details zur Implementierung der Tabellen wurden aus GrĂŒnden der Einfachheit ausgelassen. Ebenso wurden spezifische Implementierungsdetails in Bezug auf den Anwendungsbereich weggelassen.
Implementierung
Wir erstellen Rollen, Schemata, eine Tabelle
Erstellung von Datenbankobjekten
CREATE ROLE store;
CREATE SCHEMA store AUTHORIZATION store;
CREATE TABLE store.docs
(
id integer , --ID des Dokuments
man_id integer , --ID des Dokumentenmanagers
stat_id integer , --ID des Dokumentenstatus
...
is_del BOOLEAN DEFAULT FALSE
);
ALTER TABLE store.docs ADD CONSTRAINT doc_pk PRIMARY KEY (id);
ALTER TABLE store.docs OWNER TO store ;
Wir erstellen Funktionen zur Implementierung von RLS
ĂberprĂŒfung der Möglichkeit, eine Zeile auszuwĂ€hlen
check_select
ERSTELLEN ODER ERSETZEN DER FUNKTION store.check_select ( current_id store.docs.id%TYPE ) GIBT BOOLEAN ZURĂCK AS $$
DECLARE
result BOOLEAN;
curr_pid INTEGER;
curr_stat_id INTEGER;
doc_man_id INTEGER;
BEGIN
-- DBA hat Zugriff auf alle Dokumente
IF SESSION_USER = 'curr_dba'
THEN
RETURN TRUE;
END IF;
--------------------------------
--Wenn das Dokument das Label 'gelöscht' hat, nicht in der Auswahl anzeigen
SELECT
is_del
INTO
result
FROM
store.docs
WHERE
id = current_id;
IF result = TRUE
THEN
RETURN FALSE;
END IF;
--------------------------------
--Aktuelle Benutzer-ID abrufen
SELECT
service_function.get_curr_pid()
INTO
curr_pid;
--------------------------------
--ID des Dokumentenmanagers abrufen
SELECT
man_id
INTO
doc_man_id
FROM
store.docs
WHERE
id = current_id;
--------------------------------
--Wenn der Dokumentenmanager nicht der aktuelle Benutzer oder kein Manager zugewiesen ist
--das Dokument zur Auswahl hinzufĂŒgen
IF doc_man_id != curr_pid OR doc_man_id IS NULL
THEN
RETURN TRUE;
ELSE
--Aktuellen Dokumentenstatus abrufen
SELECT
stat_id
INTO
curr_statid
FROM
store.docs
WHERE
id = current_id;
--Wenn der Status das Ansehen des Dokuments erlaubt - Dokument zur Auswahl hinzufĂŒgen
IF curr_statid = 4 OR curr_statid = 9
THEN
RETURN TRUE;
ELSE
--Sonst - Dokument von der Auswahl ausschlieĂen
RETURN FALSE;
END IF;
END IF;
--------------------------------
RETURN FALSE;
END
$$ SPRACHE plpgsql SICHERHEITSDEFINIERER;
ĂNDERN FUNKTION store.check_select( store.docs.id%TYPE ) EIGENTĂMER ZU store;
WIDERRUFEN AUSFĂHRUNG FĂR FUNKTION store.check_select( store.docs.id%TYPE ) VON public;
GewĂ€hren Sie AUSFĂHRUNG FĂR FUNKTION store.check_select( store.docs.id%TYPE ) AN service_functions;
ĂberprĂŒfung der Möglichkeit, eine Zeile INSERT zu erstellen
check_insert
ERSTELLEN ODER ERSETZEN DER FUNKTION store.check_insert ( current_id store.docs.id%TYPE ) GIBT BOOLEAN ZURĂCK AS $$
DECLARE
curr_role_id INTEGER;
BEGIN
--DBA kann in jedem Fall eine Zeile hinzufĂŒgen
IF SESSION_USER = 'curr_dba'
THEN
RETURN TRUE;
END IF;
--------------------------------
--ID der Rolle des aktuellen Benutzers abrufen
SELECT
service_functions.current_rid()
INTO
curr_role_id;
--------------------------------
--Wenn die Rolle die Erstellung eines neuen Dokuments erlaubt
--erlauben
IF curr_role_id = 3 OR curr_role_id = 5
THEN
RETURN TRUE;
END IF;
--------------------------------
RETURN FALSE;
END
$$ SPRACHE plpgsql SICHERHEITSDEFINIERER;
ĂNDERN FUNKTION store.check_insert( store.docs.id%TYPE ) EIGENTĂMER ZU store;
WIDERRUFEN AUSFĂHRUNG FĂR FUNKTION store.check_insert( store.docs.id%TYPE ) VON public;
GewĂ€hren Sie AUSFĂHRUNG FĂR FUNKTION store.check_insert( store.docs.id%TYPE ) AN service_functions;
ĂberprĂŒfung der Möglichkeit, eine Zeile DELETE auszufĂŒhren
check_delete
ERSTELLEN ODER ERSETZEN DER FUNKTION store.check_delete ( current_id store.docs.id%TYPE )
GIBT BOOLEAN ZURĂCK AS $$
BEGIN
--Nur DBA kann eine Zeile löschen
IF SESSION_USER = 'curr_dba'
THEN
RETURN TRUE;
END IF;
--------------------------------
RETURN FALSE;
END
$$ SPRACHE plpgsql
SICHERHEITSDEFINIERER;
ĂNDERN FUNKTION store.check_delete( store.docs.id%TYPE ) EIGENTĂMER ZU store;
WIDERRUFEN AUSFĂHRUNG FĂR FUNKTION store.check_delete( store.docs.id%TYPE ) VON public;ĂberprĂŒfung der Möglichkeit, eine Zeile UPDATE auszufĂŒhren.
update_using
ERSTELLEN ODER ERSETZEN FUNKTION store.update_using ( current_id store.docs.id%TYPE , is_del boolean )
GIBT boolean ZURĂCK AS $$
BEGIN
--Dokumente mit dem Status ' gelöscht ' können nicht bearbeitet werden
WENN is_del
DANN
ZURĂCKGEBEN FALSE ;
SONST
ZURĂCKGEBEN TRUE ;
END IF ;
END
$$ SPRACHE plpgsql SICHERHEITSDEFINIERER;
ALTERE FUNKTION store.update_using( store.docs.id%TYPE , boolean ) EIGENTĂMER ZU store ;
WIDERRUFEN AUSFĂHRUNG AUF FUNKTION store.update_using( store.docs.id%TYPE , boolean ) VON public;
GEWĂHREN AUSFĂHRUNG AUF FUNKTION store.update_using( store.docs.id%TYPE ) AN service_functions;update_check
ERSTELLEN ODER ERSETZEN FUNKTION store.update_with_check ( current_id store.docs.id%TYPE , is_del boolean )
GIBT boolean ZURĂCK AS $$
DEKLARIEREN
current_rid integer ;
current_statid integer ;
BEGIN
--DBA kann Zeile anzeigen
WENN SESSION_USER = 'curr_dba'
DANN
ZURĂCKGEBEN TRUE ;
END IF ;
--------------------------------
--Aktuelle Benutzerrolle abrufen
SELECT
service_functions.current_rid()
IN
er curr_role_id ;
--------------------------------
--Löschung des Dokuments - Status Àndern
WENN is_deleted
DANN
--Wenn Benutzerrolle ***
WENN current_role_id = 3
DANN
SELECT
stat_id
IN
er curr_statid
VON
store.docs
WO
id = current_id ;
--Dokument im Status *** kann nicht gelöscht werden
WENN current_status_id = 11
DANN
ZURĂCKGEBEN FALSE ;
SONST
--Dokument in anderen Status kann gelöscht werden
ZURĂCKGEBEN TRUE ;
END IF ;
--Sonst, wenn Benutzerrolle ***
ELSIF current_role_id = 5
DANN
--Alle Dokumentstatus
ZURĂCKGEBEN TRUE ;
SONST
--Andere Benutzer können Dokumente nicht löschen
ZURĂCKGEBEN FALSE ;
END IF ;
SONST
--Aktualisierung des Dokuments erlaubt
ZURĂCKGEBEN TRUE ;
END IF ;
ZURĂCKGEBEN FALSE ;
END
$$ SPRACHE plpgsql SICHERHEITSDEFINIERER;
ALTERE FUNKTION store.update_with_check( storg.docs.id%TYPE , boolean ) EIGENTĂMER ZU store ;
WIDERRUFEN AUSFĂHRUNG AUF FUNKTION store.update_with_check( storg.docs.id%TYPE , boolean ) VON public;
GEWĂHREN AUSFĂHRUNG AUF FUNKTION store.update_with_check( store.docs.id%TYPE ) AN service_functions;Aktivierung der Zeilenebene-Sicherheitsrichtlinie fĂŒr die Tabelle.
ZEILENEBENE-SICHERHEIT AKTIVIEREN
ALTER TABLE store.docs ZEILENEBENE-SICHERHEIT AKTIVIEREN ;
ERSTELLEN RICHTLINIE doc_select AUF store.docs FĂR SELECT AN service_functions VERWENDEN ( (SELECT store.check_select(id)) );
ERSTELLEN RICHTLINIE doc_insert AUF store.docs FĂR INSERT AN service_functions MIT PRĂFUNG ( (SELECT store.check_insert(id)) );
ERSTELLEN RICHTLINIE docs_delete AUF store.docs FĂR DELETE AN service_functions VERWENDEN ( (SELECT store.check_delete(id)) );
ERSTELLEN RICHTLINIE doc_update_using AUF store.docs FĂR UPDATE AN service_functions VERWENDEN ( (SELECT store.update_using(id , is_del )) );
ERSTELLEN RICHTLINIE doc_update_check AUF store.docs FĂR UPDATE AN service_functions MIT PRĂFUNG ( (SELECT store.update_with_check(id , is_del )) );Fazit
Das funktioniert.
Die vorgeschlagene Strategie ermöglichte es, die Implementierung des Rollenmodells von der Ebene der GeschÀftsprozesse auf die Ebene der Datenspeicherung zu verlagern.
Funktionen können als Vorlage fĂŒr die Implementierung ausgeklĂŒgelterer Datenverbergungsmodelle dienen, wenn dies die GeschĂ€ftserfordernisse verlangen.
Quelle: habr.com
