CodeGym /Kurse /SQL SELF /Zeilenbasierte Zugriffskontrolle: Row-Level Security (RLS...

Zeilenbasierte Zugriffskontrolle: Row-Level Security (RLS)

SQL SELF
Level 47 , Lektion 3
Verfügbar

Wenn Rechte auf Rollen- und Tabellenebene wie ein "Türsteher am Haupteingang" sind, dann ist Row-Level Security wie ein persönlicher Security, der prüft, ob ein bestimmter User in jeden einzelnen Raum im Gebäude darf.

RLS sorgt dafür, dass ein User nur mit den Zeilen in einer Tabelle arbeiten kann, für die er auch wirklich berechtigt ist. Zum Beispiel:

  • Im Online-Shop soll ein Manager nur seine eigenen Bestellungen sehen.
  • In einer CRM-Plattform sieht ein Mitarbeiter nur die Kunden seines Teams.
  • Im Bankensystem darf ein Kunde nur auf seine eigenen Konten zugreifen.

Wie funktioniert RLS

Das Herzstück von RLS sind Zugriffsrichtlinien. Diese Richtlinien legen fest, welche Zeilen einer Tabelle für eine Rolle oder einen User sichtbar sind und welche geändert werden dürfen (INSERT, UPDATE, DELETE).

Standardmäßig ist RLS deaktiviert für alle Tabellen und muss manuell eingeschaltet werden.

RLS für eine Tabelle aktivieren

Lass uns eine Tabelle orders anlegen, in der die Bestellungen eines Online-Shops gespeichert werden:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    user_id INT NOT NULL,
    product_name TEXT NOT NULL,
    price NUMERIC NOT NULL
);

Fügen wir ein paar Testdaten hinzu:

INSERT INTO orders (user_id, product_name, price)
VALUES
    (1, 'Smartphone', 500),
    (2, 'Laptop', 1000),
    (1, 'Kopfhörer', 100),
    (3, 'Tastatur', 50);

Jetzt schalten wir RLS für diese Tabelle ein:

ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

Was haben wir gemacht? Wir haben den RLS-Mechanismus aktiviert, aber noch keine Richtlinien gesetzt. Solange keine Richtlinien existieren, hat RLS eigentlich keinen Einfluss auf den Zugriff auf die Tabelle.

Eine Zugriffsrichtlinie erstellen

Um Regeln für den Zugriff zu setzen, benutzt man den Befehl:

CREATE POLICY name_der_richtlinie
ON tabelle
[FOR { SELECT | INSERT | UPDATE | DELETE }]
TO rolle
USING (zugriffsbedingung)
WITH CHECK (prüfbedingung);
  • FOR: legt fest, für welche Operationen die Richtlinie gilt (SELECT, INSERT, UPDATE, DELETE). Wenn du das weglässt, gilt die Richtlinie für alle Operationen.
  • TO: gibt an, für welche Rollen die Richtlinie aktiv ist. Wenn nicht angegeben, gilt sie für jede Rolle.
  • USING: definiert die Bedingung, unter der Zeilen für den User sichtbar sind.
  • WITH CHECK: legt die Prüfbedingung für INSERT und UPDATE fest.

Beispiel: Zugriff nur auf eigene Bestellungen

Wir erstellen eine Richtlinie, die es Usern erlaubt, nur ihre eigenen Bestellungen zu sehen. Der aktuelle User hat die gleiche ID wie user_id in der Tabelle:

CREATE POLICY user_can_view_own_orders
ON orders
FOR SELECT
USING (user_id = current_user::INT);

Was passiert hier?

  • Die Richtlinie heißt user_can_view_own_orders.
  • Sie gilt für die Operation SELECT.
  • Nur Zeilen, bei denen user_id mit der ID des aktuellen Users (current_user) übereinstimmt, sind sichtbar.

Also, wenn du als User mit user_id = 1 eingeloggt bist, siehst du nur deine eigenen Bestellungen.

RLS testen

Wir legen zwei User an: user1 und user2.

CREATE ROLE user1 LOGIN PASSWORD 'password1';
CREATE ROLE user2 LOGIN PASSWORD 'password2';

Wir geben den Rollen Zugriff auf die Tabelle:

GRANT SELECT ON orders TO user1, user2;

Jetzt wechseln wir zu user1 und probieren eine Abfrage:

SELECT * FROM orders;

Ergebnis: Du siehst nur die Zeilen, bei denen user_id = 1 ist.

Richtlinien für INSERT

Sagen wir, wir wollen, dass User nur ihre eigenen Bestellungen hinzufügen dürfen (also muss user_id mit der ID des aktuellen Users übereinstimmen).

Wir erstellen eine Richtlinie für INSERT:

CREATE POLICY user_can_insert_own_orders
ON orders
FOR INSERT
WITH CHECK (user_id = current_user::INT);

Jetzt, wenn user1 versucht, eine Bestellung hinzuzufügen, bei der user_id nicht 1 ist, gibt es einen Fehler.

Richtlinien für UPDATE und DELETE

Genauso kannst du Richtlinien für das Ändern und Löschen von Daten erstellen. Zum Beispiel:

Um eigene Daten zu aktualisieren:

CREATE POLICY user_can_update_own_orders
ON orders
FOR UPDATE
USING (user_id = current_user::INT)
WITH CHECK (user_id = current_user::INT);

Um eigene Daten zu löschen:

CREATE POLICY user_can_delete_own_orders
ON orders
FOR DELETE
USING (user_id = current_user::INT);

Mehrere Richtlinien anwenden

Du kannst mehrere Richtlinien für eine Tabelle erstellen. Sie gelten dann alle gleichzeitig. Wenn für eine Rolle mehrere Regeln existieren, prüft PostgreSQL sie alle (logisches UND).

RLS prüfen und debuggen

Um zu sehen, welche Richtlinien für eine Tabelle gesetzt sind, benutze den Befehl:

\di+ tabellenname

Wenn du RLS temporär deaktivieren willst (z.B. für einen Admin), führe aus:

ALTER TABLE orders DISABLE ROW LEVEL SECURITY;

Die Admin-Rolle SUPERUSER ist standardmäßig nicht durch RLS eingeschränkt und sieht daher alle Daten.

Typische Fehler bei der RLS-Konfiguration

Fehler können passieren, wenn du vergisst:

  • RLS mit ALTER TABLE ... ENABLE ROW LEVEL SECURITY zu aktivieren.
  • Die passenden Richtlinien für alle Operationen zu setzen (SELECT, INSERT, UPDATE, DELETE).
  • Die Bedingung in USING und WITH CHECK korrekt anzugeben. Wenn du z.B. user_id nicht prüfst, öffnest du versehentlich den Zugriff auf alle Zeilen.

Row-Level Security ist eines der mächtigsten Security-Features in PostgreSQL. Damit kannst du den Zugriff bis auf die einzelne Zeile steuern und das Access-Management automatisieren – besonders wichtig für komplexe Anwendungen mit hohen Anforderungen an Datenschutz.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION