Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 7 Min.

Row Level Security

Zugang nur für geladene Gäste: Mit RLS wacht der Türsteher direkt im SQL Server.
© EMGenie

In der Welt der Datensicherheit ist Kontrolle alles. Wer darf welche Zeilen sehen, bearbeiten oder löschen? Früher musste man solche Logik mühsam in Anwendungen einbauen – mit Filtern, WHERE-Bedingungen oder eigenen Views. Doch mit Row Level Security (RLS) besitzt der SQL Server eine native Funktion, die diese Aufgabe direkt in die Datenbank verlagert. Damit entscheidet nicht mehr die Anwendung, sondern der SQL Server selbst, welche Daten ein Benutzer sehen darf. So entsteht Sicherheit auf Zeilenebene – effizient, transparent und manipulationssicher (Bild 1).

Zugriffskontrolle mit Row Level Security (Bild 1)

Zugriffskontrolle mit Row Level Security (Bild 1)

© Autor

Was ist Row Level Security?

Row Level Security ermöglicht es, Zugriffsregeln auf Datenzeilen direkt in der Datenbank-Engine zu definieren. Das bedeutet: Eine Tabelle kann für unterschiedliche Benutzer verschiedene Datensätze sichtbar machen – ohne dass die Anwendung selbst Filter implementieren muss. SQL Server prüft bei jeder Abfrage automatisch, welche Zeilen der aufrufende Benutzer sehen darf.

Das geschieht über sogenannte Security Policies, die auf Filter- oder Blockierungsfunktionen (Predicate Functions) basieren. Sie legen fest, welche Zeilen selektiert, aktualisiert oder gelöscht werden dürfen. RLS arbeitet transparent: Für den Benutzer fühlt sich alles an wie eine normale Abfrage – die Einschränkung geschieht unsichtbar im Hintergrund.

Ein einfaches Beispiel

Ein klassisches Szenario ist ein Mandantensystem, in dem mehrere Kunden auf dieselbe Datenbank zugreifen, aber nur ihre eigenen Daten sehen sollen. Oder es ist gewünscht, per Gruppenzugehörigkeit festzulegen, wer eine Zeile sehen und/oder verändern darf. Mit Row Level Security lässt sich das so abbilden:

 

CREATE TABLE [dbo].[Mitarbeiter]
 (
     [ID] [int] PRIMARY KEY CLUSTERED IDENTITY(1,1) NOT NULL,
     [Name] [varchar](100) NULL,
     [Address] [varchar](256) NULL,
     [Email] [varchar](256) NULL,
     [Gehalt] [decimal](18,2) NOT NULL,
     [SecurityDescriptor] [varchar](128) NULL
 );
 GO
 
 -- Werte einfügen
 INSERT [dbo].[Mitarbeiter] ([Name], [Address], [Email], [Gehalt], [SecurityDescriptor])
 VALUES
 ('Thorsten Kansy', 'Nidderau', 'tkansy@dotnetconsulting.eu', 15000.0, 'Chef'),
 ('James Bond', 'London', 'bond@mi5.co.uk', 10000.0, NULL),
 ('Maria Kron', 'Suffhausen', 'mk@hotmail.com', 1.0, NULL),
 ('Harry Hirsch', 'Wald', 'hh@gmail.de', 10000.0, 'CHEF');
 GO
 
 -- Funktion für Sicherheitsfilter erstellen
 CREATE FUNCTION dbo.fn_AccessFilter(@RoleOrUsername AS sysname)
     RETURNS TABLE
 WITH SCHEMABINDING -- Muss angegeben werden
 AS
 RETURN
 (
 SELECT 1 'Granted' WHERE -- Rückgabe einer Zeile => Datenzeile passiert Filter!
     USER_NAME() = @RoleOrUsername OR IS_MEMBER(ISNULL(@RoleOrUsername, 'PUBLIC')) = 1
 );
 GO
 
 -- Security Policy (Standard: aktiviert bei Erstellung)
 CREATE SECURITY POLICY SecurityFilter
     ADD FILTER PREDICATE dbo.fn_AccessFilter([SecurityDescriptor]) ON [dbo].[Mitarbeiter],
     ADD BLOCK PREDICATE dbo.fn_AccessFilter([SecurityDescriptor]) ON [dbo].[Mitarbeiter] AFTER INSERT,
     ADD BLOCK PREDICATE dbo.fn_AccessFilter([SecurityDescriptor]) ON [dbo].[Mitarbeiter] BEFORE DELETE,
     ADD BLOCK PREDICATE dbo.fn_AccessFilter([SecurityDescriptor]) ON [dbo].[Mitarbeiter] BEFORE UPDATE;
 -- Weitere Filter/ Block Prädikate für weitere Tabelle 
 GO

 

Der Trick: Die Anwendung setzt vor jeder Abfrage den aktuellen Mandanten im Session Context. SQL Server prüft automatisch, ob die Zeilen zu diesem Mandanten gehören. Das funktioniert ohne Änderung der Anwendung – jede Abfrage bleibt unverändert.

Wie RLS intern arbeitet

Row Level Security nutzt interne Predicate Functions (dbo.fn_AccessFilter im Beispiel), um Zeilen zu filtern. Diese Funktionen sind deterministisch und mit SCHEMABINDING versehen, damit sie stabil und sicher im Ausführungsplan verankert bleiben. Bei jeder Abfrage erweitert der SQL Server die WHERE-Klausel intern automatisch um die Filterbedingung der Policy.

Das hat mehrere Vorteile: Sicherheit wird zentral verwaltet, alle Clients verhalten sich konsistent, und der Schutz lässt sich nicht einfach durch geänderte SQL-Statements umgehen. Auch JOINs und Views berücksichtigen die RLS-Regeln automatisch.

RLS in Kombination mit Views und Funktionen

Row Level Security lässt sich problemlos mit Views kombinieren. Wenn eine View auf eine Tabelle mit aktiver Security Policy zugreift, greift der Filter automatisch. Das gilt auch, wenn mehrere Views übereinandergeschichtet sind. So bleibt die Sicherheitsschicht erhalten, selbst wenn Entwickler komplexe Abfragepfade nutzen.

Auch Inline-Table-Valued Functions profitieren von RLS: Sie übernehmen automatisch die Sichtbarkeitsregeln der zugrunde liegenden Tabellen. Das erleichtert die Wiederverwendung von Business-Logik, ohne separate Filterbedingungen pflegen zu müssen.

Performance und Grenzen

RLS ist performant, solange die Predicate Functions effizient sind. Sie sollten keine komplexen Joins enthalten, sondern möglichst einfache Vergleiche verwenden. Indexunterstützung bleibt vollständig erhalten, da die Filterbedingung Teil des Ausführungsplans wird. Problematisch kann es werden, wenn Policies zu viele Tabellen oder Views abdecken – dann steigt die Abfragekomplexität.

Eine häufige Frage: „Kann man RLS umgehen?“ Nein – zumindest nicht ohne administrative Rechte. RLS wird im Ausführungsplan auf Serverebene angewendet und kann weder per UNION noch per dynamisches SQL umgangen werden. Administratoren können allerdings über CONTROL SERVER-Rechte alle Zeilen sehen – das ist gewollt.

Außerdem kann es pro Tabelle nur eine aktive Policy geben. Dafür dürfen mehrere vorhanden sein, die im Wechsel aktiviert werden können.

Einsatz in der Praxis

RLS eignet sich besonders für Szenarien mit Mehrmandantenfähigkeit (Multi-Tenant-Systeme), Abteilungen mit unterschiedlichen Sichtrechten oder Anwendungen, die Daten verschiedener Kunden gemeinsam verwalten. Auch in BI-Umgebungen lässt sich RLS nutzen, um Dashboards zu personalisieren – etwa pro Region, Team oder Vertriebsleiter.

Ein Beispiel: Ein Unternehmen speichert weltweite Verkaufsdaten in einer zentralen Tabelle. Über Row Level Security sieht jeder Mitarbeiter nur die Daten seines Landes oder seiner Region. Die Abfrage ist identisch, aber das Ergebnis unterscheidet sich – ganz ohne Zusatzlogik in der Anwendung.

RLS, Application Roles und Azure AD

In modernen Architekturen spielt RLS hervorragend mit Application Roles und Azure Active Directory (Azure AD) zusammen. Ein Benutzer, der sich über Azure AD anmeldet, kann direkt in der Security Policy berücksichtigt werden. Mit Funktionen wie SESSION_CONTEXT(), ORIGINAL_LOGIN(), IS_MEMBER() et cetera lässt sich der tatsächliche Benutzer im SQL-Kontext auswerten, auch wenn Verbindungen über Pooling oder Service-Konten erfolgen.

In Cloud-Szenarien ist RLS besonders wertvoll, weil es konsistent über alle Zugriffspfade hinweg arbeitet – egal ob über ADO.NET, Power BI oder REST-APIs. Damit lassen sich Sicherheitsrichtlinien unternehmensweit durchsetzen, ohne auf Anwendungscode angewiesen zu sein.

Verwaltung und Troubleshooting

RLS-Policies werden zentral verwaltet und lassen sich einfach aktivieren oder deaktivieren:

 

ALTER SECURITY POLICY [dbo].[SecurityFilter] WITH (STATE = OFF);

 

Mit dynamischen Funktionen wie SESSION_CONTEXT(), ORIGINAL_LOGIN(), IS_MEMBER() et cetera kann man flexibel steuern, welche Benutzer welche Daten sehen. In komplexen Szenarien lässt sich auch eine Mapping-Tabelle nutzen, um Benutzerkonten bestimmten Rollen oder Regionen zuzuordnen.

Zum Testen empfiehlt sich die Nutzung von EXECUTE AS, um das Verhalten unterschiedlicher Benutzer zu simulieren:

 

EXECUTE AS USER = 'UserA'; -- Sicherheitskontext wechseln
 
 SELECT * FROM [dbo].[Mitarbeiter];
 UPDATE dbo.Mitarbeiter SET SecurityDescriptor = ...;
 DELETE [dbo].[Mitarbeiter];
 
 REVERT; -- Ursprünglicher Sicherheitskontext

 

Und keine Angst: EXECUTE AS USER ist keine Sicherheitslücke. Für deren Ausführung muss das IMPERSONATE-Recht vorliegen.

Best Practices und häufige Fehler

Wie bei jedem Sicherheitsfeature steckt der Teufel im Detail. RLS sollte nicht als Ersatz für Rollen- und Rechteverwaltung verstanden werden, sondern als Ergänzung. Die Predicate Functions gehören in ein separates Schema (zum Beispiel Security), um versehentliche Änderungen zu vermeiden.

Ein häufiger Fehler ist der Einsatz nicht deterministischer Funktionen oder externer Abfragen in Predicate Functions – das führt zu Performanceproblemen oder sogar Fehlermeldungen. Auch die Kombination von RLS mit Replikation oder In-Memory-Tabellen erfordert Vorsicht, da nicht alle Szenarien vollständig unterstützt sind.

Bewährt hat sich die Regel: Erst testen, dann aktivieren. Mit STATE = OFF kann man Policies zunächst ausrollen und prüfen, bevor sie produktiv wirken.

Sicherheit ist mehr als Sichtbarkeit

RLS schützt vor unautorisiertem Lesen – nicht aber vor indirekten Informationslecks. Ein COUNT(*) oder ein Blick in die Metadaten können zum Beispiel verraten, dass andere Daten existieren. Für vollständige Sicherheit empfiehlt sich die Kombination mit weiteren Funktionen: Dynamic Data Masking, Always Encrypted oder Separate Schemas für sensible Daten. Auch Auditing und Logging sollten aktiviert sein, um unerwartete Datenzugriffe nachvollziehen zu können.

Fazit

Row Level Security ist die elegante Antwort auf ein altes Problem: Wie begrenzt man Datenzugriffe sauber, sicher und ohne Anwendungslogik? Mit wenig Aufwand lässt sich eine mandantenfähige Struktur umsetzen, die alle SQL-Clients gleichermaßen schützt. Für Entwickler bedeutet das weniger Code, für DBAs mehr Kontrolle – und für alle zusammen ein gutes Gefühl der Sicherheit.

RLS entfaltet seine volle Wirkung, wenn es Teil eines Gesamtkonzepts ist: Klare Rollen, saubere Namenskonventionen, regelmäßige Audits und dokumentierte Zugriffsmodelle. So bleibt die Sicherheit nachvollziehbar und skalierbar – egal ob On-Premises oder in Azure.

Richtig konzipiert ist RLS kein Performance-Killer, sondern ein Sicherheitsgewinn mit klarer Architektur. Oder anders gesagt: Zugang nur für geladene Gäste – und der Türsteher übewacht direkt im SQL Server (Bild 2).

 

RLS als Türsteher (Bild 2)

RLS als Türsteher (Bild 2)

© Autor

Neueste Beiträge

Partitionierung - Acht Kostbarkeiten in T-SQL, Teil 4
Daten häppchenweise oder: Was ist Partitionierung und warum?
7 Minuten
26. Jan 2026
SignalRC braucht LTE - Der DDC-Truck, Teil 2
Das LTE-Netz als Transportkanal digitaler Steuerungsdaten bei RC-Modellen.
6 Minuten
28. Jan 2026
BRIN-Indizes in PostgreSQL - Indizes & Co. in PostgreSQL, Teil 4
PostgreSQL mit BRIN vertritt die Idee, dass ein Index unvollkommen sein kann, solange er kostengünstig und in großem Maßstab effektiv ist. So entsteht eine pragmatische Optimierung, die Präzision gegen Einfachheit eintauscht – und dabei gewinnt.
6 Minuten

Das könnte Dich auch interessieren

GiST- und SP-GiST-Indizes in PostgreSQL - Indizes & Co. in PostgreSQL, Teil 2
GiST ermöglicht es Indizes in PostgreSQL, Beziehungen wie Überschneidung, Einschluss und Entfernung zu verstehen. SP-GiST hingegen erlaubt es Indizes, saubere Partitionen in hierarchischen oder präfixbasierten Daten auszunutzen.
7 Minuten
Partitionierung - Acht Kostbarkeiten in T-SQL, Teil 4
Daten häppchenweise oder: Was ist Partitionierung und warum?
7 Minuten
26. Jan 2026
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige