Если права на уровне ролей и таблиц — это "охранник у входной двери", то Row-Level Security — это индивидуальный охранник, который проверяет, можно ли тому или иному пользователю заходить в каждую отдельную комнату в здании.
RLS помогает сделать так, чтобы пользователь мог работать только с теми строками в таблице, которые ему разрешены. Например:
- В интернет-магазине менеджер должен видеть только свои заказы.
- В CRM-платформе сотрудник видит только клиентов своей команды.
- В банковской системе клиент должен иметь доступ только к своим счетам.
Как работает RLS
В основе работы RLS лежит концепция политик доступа. Политики определяют, какие строки таблицы видимы для роли или пользователя и какие доступны для изменений (INSERT, UPDATE, DELETE).
По умолчанию RLS отключён для всех таблиц, и включить его можно вручную.
Включение RLS для таблицы
Давайте создадим таблицу orders, где хранятся заказы интернет-магазина:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
user_id INT NOT NULL,
product_name TEXT NOT NULL,
price NUMERIC NOT NULL
);
Добавим несколько тестовых данных:
INSERT INTO orders (user_id, product_name, price)
VALUES
(1, 'Смартфон', 500),
(2, 'Ноутбук', 1000),
(1, 'Наушники', 100),
(3, 'Клавиатура', 50);
Теперь включим RLS для этой таблицы:
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
Что мы сделали? Мы активировали механизм RLS, но сами политики ещё не установлены. Пока политики не созданы, RLS фактически не влияет на доступ к таблице.
Создание политики доступа
Чтобы добавлять правила для управления доступом, используется команда:
CREATE POLICY имя_политики
ON таблица
[FOR { SELECT | INSERT | UPDATE | DELETE }]
TO роль
USING (условие_доступа)
WITH CHECK (условие_проверки);
FOR: определяет, для каких операций применяется политика (SELECT,INSERT,UPDATE,DELETE). Если пропустить этот параметр, политика применяется ко всем операциям.TO: указывает, для каких ролей политика активна. Если не указано, политика применяется к любой роли.USING: задаёт условие, при выполнении которого строки будут видны пользователю.WITH CHECK: определяет условие проверки для операцийINSERTиUPDATE.
Пример: доступ только к своим заказам
Создадим политику, которая разрешает пользователям видеть только свои заказы. Пусть идентификатор текущего пользователя совпадает с user_id в таблице:
CREATE POLICY user_can_view_own_orders
ON orders
FOR SELECT
USING (user_id = current_user::INT);
Что здесь происходит?
- Политика называется
user_can_view_own_orders. - Она применяется к операции
SELECT. - Только строки, где
user_idсовпадает с идентификатором текущего пользователя (current_user), видимы.
Итак, если вы вошли в систему как пользователь с user_id = 1, вы увидите только свои заказы.
Проверка работы RLS
Создадим двух пользователей: user1 и user2.
CREATE ROLE user1 LOGIN PASSWORD 'password1';
CREATE ROLE user2 LOGIN PASSWORD 'password2';
Назначим роли доступ к таблице:
GRANT SELECT ON orders TO user1, user2;
Теперь переключимся на пользователя user1 и попробуем выполнить запрос:
SELECT * FROM orders;
Результат: вы увидите только строки, где user_id = 1.
Политики для INSERT
Скажем, мы хотим разрешить пользователям добавлять только свои заказы (т.е. строка с user_id должна совпадать с идентификатором текущего пользователя).
Создадим политику на INSERT:
CREATE POLICY user_can_insert_own_orders
ON orders
FOR INSERT
WITH CHECK (user_id = current_user::INT);
Теперь, если пользователь user1 попытается добавить заказ, где user_id не равен 1, то запрос завершится с ошибкой.
Политики для UPDATE и DELETE
Подобным образом можно создавать политики для изменения и удаления данных. Например:
Для обновления своих данных:
CREATE POLICY user_can_update_own_orders
ON orders
FOR UPDATE
USING (user_id = current_user::INT)
WITH CHECK (user_id = current_user::INT);
Для удаления своих данных:
CREATE POLICY user_can_delete_own_orders
ON orders
FOR DELETE
USING (user_id = current_user::INT);
Применение нескольких политик
Вы можете создать несколько политик для одной таблицы. Все они будут применяться одновременно. Например, если для одной роли действует несколько правил, PostgreSQL проверит их все (логическое И).
Проверка и отладка RLS
Чтобы проверить, какие политики установлены для таблицы, используйте команду:
\di+ имя_таблицы
Если вы хотите временно отключить RLS (например, для администратора), выполните:
ALTER TABLE orders DISABLE ROW LEVEL SECURITY;
Администраторская роль SUPERUSER по умолчанию не ограничена RLS, поэтому может видеть все данные.
Типичные ошибки при настройке RLS
Ошибки могут возникнуть, если вы забудете:
- Активировать RLS командой
ALTER TABLE ... ENABLE ROW LEVEL SECURITY. - Установить соответствующие политики для всех операций (
SELECT,INSERT,UPDATE,DELETE). - Корректно указать условие в
USINGиWITH CHECK. Например, не проверивuser_id, можно случайно открыть доступ ко всем строкам.
Row-Level Security — это один из самых мощных инструментов безопасности в PostgreSQL. Он позволяет настроить доступ с точностью до строки и автоматизировать управление доступом, что особенно важно для сложных приложений с высокими требованиями к защите данных.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ