0Pricing
SQL Academy · Урок

Политики безопасности на уровне строк

Автоматически фильтруйте строки для каждого пользователя

«Политики безопасности на уровне строк» — бесплатный урок SQL Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения SQL Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс SQL Academy содержит 4 уроков всего.

Что такое безопасность на уровне строк

Безопасность на уровне строк (RLS) — это функция PostgreSQL, которая позволяет управлять тем, какие строки таблицы конкретный пользователь или роль базы данных может видеть или изменять. Вместо фильтрации строк в каждом запросе Вы один раз определяете политику, а PostgreSQL автоматически применяет её для каждого SELECT, INSERT, UPDATE и DELETE.

Представьте её как невидимое предложение WHERE, прикреплённое к самой таблице, а не к конкретному запросу.

Включение RLS для таблицы

По умолчанию RLS отключена. Её необходимо явно включить для каждой таблицы с помощью ALTER TABLE ... ENABLE ROW LEVEL SECURITY. После включения любая роль, не являющаяся владельцем таблицы, не увидит ни одной строки, пока не будет создана хотя бы одна политика.

-- Create a sample table
CREATE TABLE orders (
  id        SERIAL PRIMARY KEY,
  owner     TEXT NOT NULL,
  amount    NUMERIC(10,2)
);

-- Enable RLS
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

Создание первой политики

Политика создаётся с помощью CREATE POLICY. Ей присваивается имя, указывается таблица и задаётся выражение USING. Предложение USING содержит логическое выражение, которое вычисляется для каждой строки: пользователю видны только строки, для которых выражение возвращает TRUE.

-- Allow each user to see only their own orders
CREATE POLICY orders_owner_policy
  ON orders
  FOR SELECT
  USING (owner = current_user);

Условия USING и WITH CHECK

Политики содержат два условия фильтрации, служащих разным целям:

  • USING — фильтрует строки при операциях чтения (SELECT, UPDATE, DELETE). Строка видима, только если USING возвращает TRUE.
  • WITH CHECK — проверяет строки при операциях записи (INSERT, UPDATE). Запись разрешена, только если WITH CHECK возвращает TRUE. Если WITH CHECK не указано, USING повторно используется для проверки записи.
-- Allow users to select and insert only their own rows
CREATE POLICY orders_isolation
  ON orders
  FOR ALL
  USING       (owner = current_user)
  WITH CHECK  (owner = current_user);

Область действия политики: FOR SELECT, INSERT, UPDATE, DELETE

Одна политика может охватывать все команды (FOR ALL) или одну конкретную команду. Разделение политик по командам дает тонкий контроль — например, позволяет каждому пользователю читать все строки, но изменять только свои.

-- Everyone can read all orders
CREATE POLICY read_all_orders
  ON orders
  FOR SELECT
  USING (true);

-- But each user can only update their own orders
CREATE POLICY update_own_orders
  ON orders
  FOR UPDATE
  USING       (owner = current_user)
  WITH CHECK  (owner = current_user);

Использование session_user и current_user

PostgreSQL предоставляет встроенные функции для определения активного пользователя внутри выражения политики:

  • current_user — роль, чьи привилегии в данный момент активны (может измениться после SET ROLE).
  • session_user — роль, открывшая соединение (не изменяется в течение сеанса).

В большинстве политик RLS используется current_user, поскольку он отражает действующую роль после переключения ролей.

-- Inspect the current identity inside a query
SELECT current_user, session_user;

Применение RLS к определенным ролям

По умолчанию политика применяется к PUBLIC (всем ролям). Вы можете ограничить ее конкретной ролью с помощью оговорки TO. Это полезно, когда для обычных пользователей нужна одна политика, а для роли администратора — другая.

-- Policy only for the 'app_user' role
CREATE POLICY app_user_policy
  ON orders
  FOR SELECT
  TO app_user
  USING (owner = current_user);

-- Separate permissive policy for 'admin' role
CREATE POLICY admin_full_access
  ON orders
  FOR ALL
  TO admin
  USING (true)
  WITH CHECK (true);

Политики PERMISSIVE и RESTRICTIVE

Несколько политик для одной таблицы могут взаимодействовать двумя способами:

  • PERMISSIVE (по умолчанию) — все разрешающие политики объединяются с помощью OR. Строка доступна, если ее разрешает хотя бы одна разрешающая политика.
  • RESTRICTIVE — ограничивающие политики объединяются с результатом разрешающих политик с помощью AND. Строка доступна, только если она проходит ограничивающую политику и хотя бы одну разрешающую политику.
-- Restrictive policy: block access to archived orders for everyone
CREATE POLICY no_archived_rows
  ON orders
  AS RESTRICTIVE
  FOR SELECT
  USING (amount > 0);

Обход RLS: BYPASSRLS и владельцы таблиц

Владелец таблицы и суперпользователи по умолчанию обходят RLS и всегда видят все строки. Вы можете предоставить роли атрибут BYPASSRLS, если ей нужен неограниченный доступ без прав суперпользователя. И наоборот, можно заставить владельца соблюдать RLS с помощью FORCE ROW LEVEL SECURITY.

-- Force the table owner to also obey RLS policies
ALTER TABLE orders FORCE ROW LEVEL SECURITY;

-- Grant BYPASSRLS to a trusted service account
ALTER ROLE service_account BYPASSRLS;

Изменение и удаление политик

Вы можете изменить существующую политику с помощью ALTER POLICY или полностью удалить ее с помощью DROP POLICY. Удаление всех политик при включенном RLS означает, что роли, не являющиеся владельцами, не смогут получить доступ ни к одной строке. Чтобы полностью удалить RLS, отключите его с помощью ALTER TABLE.

-- Rename a policy
ALTER POLICY orders_owner_policy ON orders
  RENAME TO user_isolation_policy;

-- Update the USING expression
ALTER POLICY user_isolation_policy ON orders
  USING (owner = current_user AND amount >= 0);

-- Remove a policy
DROP POLICY admin_full_access ON orders;

-- Disable RLS entirely on the table
ALTER TABLE orders DISABLE ROW LEVEL SECURITY;

Практический шаблон: изоляция данных между арендаторами

Распространенный шаблон RLS в многотенантных SaaS-приложениях — добавление столбца tenant_id в каждую таблицу и использование переменной уровня сеанса (set_config) для передачи идентификатора арендатора при установлении соединения. Затем политика сравнивает tenant_id каждой строки с этим значением.

-- Table with tenant isolation column
CREATE TABLE documents (
  id         SERIAL PRIMARY KEY,
  tenant_id  TEXT NOT NULL,
  title      TEXT
);

ALTER TABLE documents ENABLE ROW LEVEL SECURITY;

-- Policy reads the tenant from a session variable
CREATE POLICY tenant_isolation
  ON documents
  FOR ALL
  USING       (tenant_id = current_setting('app.tenant_id'))
  WITH CHECK  (tenant_id = current_setting('app.tenant_id'));

-- Application sets the variable before running queries
SELECT set_config('app.tenant_id', 'tenant_42', true);

-- Now only tenant_42 documents are visible
SELECT * FROM documents;

Проверка знаний

Проверьте понимание политик безопасности на уровне строк в PostgreSQL.

Итоги урока

В этом уроке Вы узнали, как безопасность на уровне строк автоматически фильтрует строки на уровне базы данных на основе политик:

  • Включите RLS в таблице с помощью ALTER TABLE ... ENABLE ROW LEVEL SECURITY.
  • Используйте CREATE POLICY с условием USING для фильтрации доступных для чтения строк и с условием WITH CHECK для проверки записываемых строк.
  • Ограничивайте политики конкретными командами (SELECT, INSERT, UPDATE, DELETE, ALL) и ролями с помощью оговорки TO.
  • Объединяйте политики PERMISSIVE (логика OR) и RESTRICTIVE (логика AND) для многоуровневого управления доступом.
  • Владельцы таблиц и суперпользователи по умолчанию обходят RLS; используйте FORCE ROW LEVEL SECURITY, чтобы изменить это поведение.
  • Шаблон для нескольких арендаторов с использованием current_setting() — мощный практический пример применения RLS.

RLS — стандартный способ надежно и единообразно изолировать данные, не распределяя условия WHERE по каждому запросу приложения.

Часто задаваемые вопросы

Урок «Политики безопасности на уровне строк» бесплатный?

Да — полный текст урока «Политики безопасности на уровне строк» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс SQL Academy, подпишись на CoddyKit PRO. Курс SQL Academy содержит 4 уроков всего.

Чему я научусь в уроке «Политики безопасности на уровне строк»?

Автоматически фильтруйте строки для каждого пользователя Ты практикуешь SQL Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать SQL Academy?

Предыдущий опыт не требуется. SQL Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Политики безопасности на уровне строк»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке SQL Academy?

Да. Каждый урок SQL Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Роли и привилегии
  2. Политики безопасности на уровне строк
  3. Разрешения на уровне столбцов
  4. Аудит доступа
← Назад к SQL Academy