---
term: 'Zeilenbasierte Sicherheit (RLS)'
seoTitle: 'Zeilenbasierte Sicherheit (RLS): Policies, Fallstricke, Praxis'
headline: 'Was ist zeilenbasierte Sicherheit (RLS)?'
slug: zeilenbasierte-sicherheit-rls
category: database
shortDefinition: 'Zeilenbasierte Sicherheit ist ein Datenbankmechanismus, bei dem Policies bei jeder Abfrage filtern, welche Zeilen jemand sehen oder ändern darf.'
relatedTerms:
  - access-control-lists-acl
  - class-level-permissions-clp
  - role-based-access-control-rbac
  - tenant-isolation
  - data-layer-vs-application-layer-security
contrastsWith:
  - class-level-permissions-clp
faq:
  - question: 'Was ist zeilenbasierte Sicherheit, einfach erklärt?'
    answer: 'Eine erzwungene, unsichtbare WHERE-Klausel. Sie hängen Policies an eine Tabelle, und die Datenbank wendet deren Bedingungen automatisch auf jede Abfrage an – jeder Benutzer sieht und ändert nur die Zeilen, die die Policy erlaubt, ganz gleich welche Abfrage er schreibt oder welches Werkzeug er benutzt. Der Filter liegt in der Datenbank, also kann ihn kein Codepfad der Anwendung vergessen.'
  - question: 'Wie funktioniert zeilenbasierte Sicherheit?'
    answer: 'Sie aktivieren RLS auf einer Tabelle und legen Policies mit booleschen Prädikaten an – die typischerweise die Eigentümer- oder Tenant-Spalte einer Zeile mit dem aktuellen Benutzer oder einer Session-Variablen vergleichen. Zur Abfragezeit wertet die Engine das Prädikat pro Zeile aus, bevor die eigenen Bedingungen des Benutzers greifen, filtert Lesezugriffe und blockiert unerlaubte Schreibzugriffe. Ist RLS einmal ohne Policy aktiviert, gilt standardmäßig: alles verboten.'
  - question: 'Was ist der Unterschied zwischen USING und WITH CHECK?'
    answer: 'Die Richtung. USING filtert, was für Sie existiert: Zeilen, die für SELECT sichtbar und für UPDATE oder DELETE zugänglich sind. WITH CHECK prüft, was Sie schreiben: einzufügende Zeilen und die neuen Werte nach einem Update. Lassen Sie WITH CHECK weg, gilt das USING-Prädikat für beides – aber Tabellen, in denen Benutzer breit lesen und eng schreiben dürfen, brauchen beide, unterschiedlich definiert.'
  - question: 'Wer kann zeilenbasierte Sicherheit umgehen?'
    answer: 'In PostgreSQL: Superuser, Rollen mit BYPASSRLS und – der Fall, den alle vergessen – der Eigentümer der Tabelle, sofern Sie nicht FORCE ROW LEVEL SECURITY setzen. Diese Umgehungsmatrix zu auditieren gehört zum Ausrollen von RLS; eine perfekte Policy schützt nichts, wenn die Anwendung sich als Tabelleneigentümer verbindet.'
  - question: 'Kostet zeilenbasierte Sicherheit Performance?'
    answer: 'Sie kann es – das Prädikat der Policy wird bei jeder Abfrage gegen die Kandidatenzeilen ausgewertet. Die Gegenmaßnahmen sind über alle Produktionserfahrungen hinweg dieselben: Indizieren Sie die Spalten, auf die Ihre Policies verweisen, halten Sie Prädikate frei von Joins (nutzen Sie stattdessen Funktionen oder Rollenprüfungen) und kapseln Sie Funktionen pro Anfrage so, dass sie einmal pro Abfrage statt einmal pro Zeile ausgewertet werden. Eine Policy auf einer nicht indizierten Spalte ist ein Table Scan mit Sicherheitsabzeichen.'
  - question: 'Was ist der Unterschied zwischen RLS und Filterung in der Anwendung?'
    answer: 'Wo die Grenze liegt. Filterung in der Anwendung grenzt Abfragen im Code ein – flexibel, aber in jedem Codepfad dupliziert und von allem umgangen, was direkt mit der Datenbank spricht. RLS setzt in der Engine durch und deckt jeden Zugriffspfad ab, Admin-Werkzeuge und andere Dienste eingeschlossen. Der Konsens lautet mehrschichtige Verteidigung: in der Anwendung eingrenzen für die Klarheit, in der Datenbank durchsetzen für die Sicherheit.'
  - question: 'Wie funktioniert RLS mit Connection Pooling?'
    answer: 'Mit Vorsicht. Anwendungen mit Pool verbinden sich als ein einziger Datenbankbenutzer, deshalb stützen sich Policies auf eine Session-Variable pro Anfrage statt auf die Identität der Verbindung – gesetzt beim Entnehmen, gelesen von der Policy, zurückgesetzt bei der Rückgabe. Bei Poolern im Transaktionsmodus muss die Einstellung transaktionsweit gelten, sonst sickert der Kontext eines Tenants in die nächste Anfrage auf derselben Verbindung. Dieses Zusammenspiel ist der häufigste RLS-Fehler im Produktivbetrieb.'
  - question: 'Wie testet man Policies für zeilenbasierte Sicherheit?'
    answer: 'Schlüpfen Sie in jede Rolle und führen Sie alle vier Operationen aus – select, insert, update, delete – und prüfen Sie sowohl, was erscheint, als auch, was verweigert wird. Ergänzen Sie die beiden vergessenen Fälle: den ungesetzten Kontext (keine gesetzte Tenant-Variable muss keine Zeilen bedeuten, nicht alle) und die Umgehungsmatrix (Eigentümer, Superuser, Replikationspfade). RLS verdient sich Vertrauen durch feindselige Tests, nicht dadurch, dass die Policy sich gut liest.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'PostgreSQL Row Security Policies'
    url: 'https://www.postgresql.org/docs/current/ddl-rowsecurity.html'
  - name: 'PostgreSQL CREATE POLICY reference'
    url: 'https://www.postgresql.org/docs/current/sql-createpolicy.html'
  - name: 'Row-Level Security and Multi-Tenancy on MongoDB (Back4app Engineering)'
    url: 'https://www.back4app.com/multi-tenant-mongodb-row-level-security'
  - name: 'Backend security documentation'
    url: 'https://docs.parseplatform.org/parse-server/guide/#security'
cta:
  title: 'Zeilenbasierte Sicherheit für Ihre MongoDB'
  text: 'Back4app setzt den Zugriff pro Zeile auf einer Dokumentdatenbank ab Werk durch: Jedes Objekt trägt eine ACL, Rollen fassen Benutzer zusammen, und die Plattform prüft beides bei jeder Anfrage – jedes SDK, jede API, das Dashboard ebenso. Keine Policies von Hand, keine WHERE-Klausel zum Vergessen.'
  linkText: 'Kostenlos starten'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-09-24'
translationKey: row-level-security
---

**Zeilenbasierte Sicherheit ist ein Datenbankmechanismus, bei dem Policies bei jeder Abfrage filtern, welche Zeilen jemand sehen oder ändern darf.** Das mentale Modell ist eine *erzwungene, unsichtbare WHERE-Klausel*: Die Bedingung, an die Sie sonst in jeder Abfrage denken müssten, wird zu einer Eigenschaft der Tabelle selbst – angewendet von der Engine, auf jedem Zugriffspfad, auch auf denen, die Ihr Anwendungscode nie zu sehen bekommt.

## Das Wichtigste in Kürze

| Frage | Antwort |
| --- | --- |
| Was es ist | Zugriffskontrolle pro Zeile, durchgesetzt von der Datenbank-Engine selbst |
| Das mentale Modell | Eine WHERE-Klausel, die niemand vergessen kann |
| Der wichtigste Anwendungsfall | Multi-Tenant-Isolation und Daten pro Benutzer, in der Schicht, die ein Angriff nicht überspringen kann |
| Das Kleingedruckte | Umgehungsrollen, Default-Deny, Pooling-Kontext – die Fallstricke sind operativer Natur |
| Der Fehler, den sie verhindert | Ein vergessener Filter im Anwendungscode = Datenabfluss zwischen Tenants |

## RLS in zehn Zeilen SQL

```sql
CREATE TABLE invoices (
  tenant_id uuid NOT NULL,
  total     numeric(10,2)
);

ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;   -- ab hier: standardmäßig verboten

CREATE POLICY tenant_isolation ON invoices
  USING      (tenant_id = current_setting('app.tenant')::uuid)   -- was Sie lesen dürfen
  WITH CHECK (tenant_id = current_setting('app.tenant')::uuid);  -- was Sie schreiben dürfen

-- Jede Abfrage verhält sich nun so, als endete sie mit WHERE tenant_id = <Ihrer>.
-- Eine Abfrage, die ihren Filter vergisst, liefert nichts – nicht alles.
```

Dieselbe Garantie existiert in Dokumentdatenbanken als *Zugriffskontrolle auf der Zeile selbst* – jedes Objekt trägt seine ACL, und die Plattform setzt sie bei jeder Anfrage durch:

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK
// Row-level security as data: this row is readable by its owner, period
const note = new Parse.Object('Note');
note.set('text', 'Q3 salary planning');
note.setACL(new Parse.ACL(Parse.User.current())); // owner-only, on the row itself
await note.save();

// Later, any query by any user — the row exists only for its owner
const notes = await new Parse.Query('Note').find(); // others never see it
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// Row-level security as data: this row is readable by its owner, period
final user = await ParseUser.currentUser() as ParseUser;
final acl = ParseACL(owner: user); // owner-only, on the row itself

final note = ParseObject('Note')
  ..set('text', 'Q3 salary planning')
  ..setACL(acl);
await note.save(); // other users' queries never return this row
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// Row-level security as data: this row is readable by its owner, period
var note = Note()
note.text = "Q3 salary planning"
note.ACL = try ParseACL.defaultACL() // owner-only, on the row itself
note.save { result in
  if case .success = result {
    print("saved — other users' queries never return this row")
  }
}
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// Row-level security as data: this row is readable by its owner, period
val note = ParseObject("Note").apply {
  put("text", "Q3 salary planning")
  acl = ParseACL(ParseUser.getCurrentUser()) // owner-only, on the row itself
}
note.saveInBackground { e ->
  if (e == null) Log.d("Notes", "saved — invisible to every other user")
}
```

## Was die Engine aus einer Abfrage macht

```mermaid
flowchart LR
  accTitle: Wie zeilenbasierte Sicherheit eine Abfrage filtert
  accDescr: Zwei verschiedene Benutzer führen dieselbe Abfrage gegen eine Tabelle aus; die Engine wendet das Prädikat der Policy pro Zeile vor den Bedingungen des Benutzers an, sodass jeder nur die Zeilen erhält, die seine Policy erlaubt.
  Q["SELECT * FROM invoices<br/>(dieselbe Abfrage, beliebiger Benutzer)"] --> P["Policy-Prädikat<br/>pro Zeile, zuerst angewendet"]
  P --> A["Tenant A sieht nur<br/>Zeilen von Tenant A"]
  P --> B["Tenant B sieht nur<br/>Zeilen von Tenant B"]
```

## USING vs. WITH CHECK, permissiv vs. restriktiv

| Konzept | Regelt | Faustregel |
| --- | --- | --- |
| `USING` | Was für Sie existiert: Lesezugriffe und Zeilen, die für Update/Delete infrage kommen | "Darf ich es sehen?" |
| `WITH CHECK` | Was Sie schreiben dürfen: Inserts und die Werte nach einem Update | "Darf ich es so anlegen?" |
| Permissive Policies (Standard) | Mit OR verknüpft – ein Treffer genügt | Zugriff gewähren |
| Restriktive Policies | Mit AND darübergelegt – alle müssen passen | Zwingende Grenzen setzen |

Zwei Kompositionsregeln aus der [PostgreSQL-Referenz](https://www.postgresql.org/docs/current/sql-createpolicy.html) lohnen sich zu merken: Wer `WITH CHECK` weglässt, verwendet `USING` auch für Schreibzugriffe, und mindestens eine permissive Policy muss passen, bevor die restriktiven überhaupt herangezogen werden – nur restriktive Policies heißt: niemand kommt herein.

## Wo RLS unterstützt wird

| Engine-Familie | Mechanismus |
| --- | --- |
| PostgreSQL (9.5+) und Derivate | `CREATE POLICY` – die Referenzimplementierung |
| SQL Server (2016+) | Security-Policies über Inline-Prädikatfunktionen (filter + block) |
| Verteiltes SQL (CockroachDB, YugabyteDB) | PostgreSQL-kompatible Policies |
| Cloud-Data-Warehouses | Row Access Policies, je nach Anbieter unterschiedlich |
| Dokumentdatenbanken | Nicht policy-basiert – ACLs pro Objekt, durchgesetzt von der Plattformschicht |

Die letzte Zeile ist die, um die es in diesem Glossar geht: In Dokumentspeichern ist die Grenze auf Zeilenebene typischerweise ein *Datum auf der Zeile* (die ACL) statt ein Prädikat in der Engine – dieselbe Garantie, anderer Mechanismus, ausführlich beschrieben im [Engineering-Beitrag von Back4app](https://www.back4app.com/multi-tenant-mongodb-row-level-security).

## Die Fallstricke, endlich an einem Ort

- **Überraschungen durch Default-Deny.** RLS ohne Policy zu aktivieren sperrt alle außer dem Eigentümer aus – die Hälfte aller "RLS hat die Produktion lahmgelegt"-Geschichten ist genau das.
- **Die Umgehungsmatrix.** Superuser, `BYPASSRLS`-Rollen und *Tabelleneigentümer* überspringen Policies – setzen Sie `FORCE ROW LEVEL SECURITY`, wenn der Eigentümer zugleich der Benutzer der Anwendung ist, und auditieren Sie, wer was hält.
- **Views laufen standardmäßig mit den Rechten ihres Eigentümers** – ein View auf eine RLS-Tabelle kann sie still umgehen, sofern er nicht mit den Rechten des Aufrufers erstellt wurde (`security_invoker` in PostgreSQL).
- **Constraints verraten Existenz.** Die Verletzung einer Unique- oder Fremdschlüssel-Constraint kann offenbaren, dass eine unsichtbare Zeile existiert – der dokumentierte verdeckte Kanal; behandeln Sie Eindeutigkeit auf geschützten Werten entsprechend.
- **Fehler können Werte verraten.** Gezielt gebaute Ausdrücke, die bei bestimmten Daten fehlschlagen (eine Division durch null, wenn ein verborgener Wert passt), schleusen Informationen über Fehlermeldungen aus – die Klasse von Seitenkanälen, die die SQL-Server-Dokumentation beschreibt.
- **Dumps und Pools haben Modi.** Backup-Werkzeuge brauchen unter Umständen die abgeschaltete Zeilensicherheit, um alles zu exportieren; Pooler im Transaktionsmodus brauchen einen transaktionsweiten Kontext (`SET LOCAL`), sonst färben Tenants von Anfrage zu Anfrage ab.

## Performance: Policies sind Code auf dem heißen Pfad

Drei Regeln decken den Großteil der Praxiserfahrung ab: **Indizieren Sie jede Spalte, auf die eine Policy verweist** (das Prädikat läuft vor den eigenen Filtern Ihrer Abfrage – ohne Index ist es ein voller Table Scan); **halten Sie Prädikate frei von Joins**, indem Sie das Nachschlagen in Funktionen oder Rollenprüfungen verlagern; und **sorgen Sie dafür, dass Funktionen pro Anfrage einmal pro Abfrage ausgewertet werden, nicht einmal pro Zeile**, indem Sie sie in eine skalare Unterabfrage kapseln. Sauber gemessen kostet RLS einstellige Prozentwerte; schlecht gemessen ist es die rätselhafte Verlangsamung auf jeder Tabelle, die Sie abgesichert haben.

## Typische Anwendungsfälle

- **Multi-Tenant-SaaS.** Der kanonische Fall – Tenant-Isolation unterhalb der Anwendung durchgesetzt, dort, wo ein vergessener Filter kein Datenleck werden kann.
- **Daten pro Benutzer.** Nachrichten, Dokumente, Gesundheitsakten: Benutzer sehen ihre Zeilen, mehr nicht.
- **Abteilungs- und Regionsgrenzen.** Der Vertrieb sieht seine Region; Prüfer sehen alles, nur lesend – Policy-Schichtung in Aktion.
- **Compliance-Anforderungen.** Zugriffskontrolle, die sich auf der Datenschicht nachweisen lässt – genau dort, wo Prüfer sie sehen wollen.
- **Geteilter analytischer Zugriff.** Analysten fragen Produktionsreplikate direkt ab und sehen nur, was ihre Rolle erlaubt – sicher, *weil* die Datenbank es durchsetzt, nicht das Dashboard.

## Sollten Sie auf Zeilenebene durchsetzen? Entscheidungsmatrix

| Mit RLS/ACLs durchsetzen, wenn … | Filterung in der Anwendung kann genügen, wenn … |
| --- | --- |
| Mehrere Tenants oder Benutzer sich Tabellen teilen | Die Datenbank genau einen vertrauenswürdigen Aufrufer hat |
| Auch anderes als die App die Datenbank berührt | Keine BI-Werkzeuge, kein Admin-SQL, kein zweiter Dienst |
| Ein vergessener Filter ein Leck bedeutet, keinen Fehler | Die Eingrenzung Bequemlichkeit ist, keine Sicherheit |
| Compliance einen Nachweis auf der Datenschicht verlangt | Die Daten nicht sensibel sind |
| Sie die Grenze einmal zentral getestet haben wollen | Sie es genießen, für immer jede Abfrage zu auditieren |

Die ehrliche Zusammenfassung beider Spalten: Behalten Sie die Eingrenzung in der Anwendung, weil sie den Code lesbar hält – und setzen Sie sie trotzdem in der Datenbank durch. Mehrschichtige Verteidigung ist genau der Punkt.

## Grenzen und Trade-offs

- **Policies sind von Natur aus unsichtbar** – was das Debuggen von "wo sind meine Zeilen hin?" zu einer echten Fertigkeit macht; protokollieren Sie zuerst den Session-Kontext.
- **Komplexe Autorisierung sprengt Prädikate.** Regeln, die Workflow-Zustand oder entitätsübergreifende Logik brauchen, gehören in die Autorisierungsschicht der Anwendung, mit RLS als Auffangnetz.
- **Die operative Oberfläche ist real.** Umgehungsmatrix, Dump-Modi und Pooling-Kontext sind fortlaufendes Betriebswissen, keine einmalige Einrichtung.
- **Die Auswertung pro Zeile ist eine Steuer** – gering, wenn sauber konstruiert, unbegrenzt, wenn nicht.
- **Sie sichert Zeilen, nicht Spalten.** Felder zu verbergen ist Sicherheit auf Spaltenebene; kombinieren Sie beides für eine Wirkung auf Zellebene.

## Zeilenbasierte Sicherheit mit Back4app

Back4app ist eine Open-Source-Plattform für Backend as a Service (BaaS), die eine verwaltete Datenbank, automatisch generierte REST- und GraphQL-APIs, Authentifizierung, Dateispeicher und Serverless-Funktionen mit Cloud Code kombiniert. Das Modell auf Zeilenebene ist der ACL-als-Daten-Mechanismus aus den Tabs oben: Jedes Objekt trägt seine Zugriffsliste, Rollen bilden Tenants und Teams ab, und [die Plattform setzt beides bei jeder Anfrage durch](https://docs.parseplatform.org/parse-server/guide/#security) – SDKs, REST, GraphQL und das Dashboard inklusive, mit Klassenberechtigungen als restriktiver Schicht darüber. Es ist die Garantie der erzwungenen WHERE-Klausel, geliefert auf einer Dokumentdatenbank, mit der obigen Fallstrickliste von der Plattform absorbiert statt Ihnen aufgebürdet.
