0Pricing
SQL Academy · 课时

行级安全策略

自动按用户筛选行

行级安全策略 是 CoddyKit 上的免费 SQL Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 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 时,才允许写入。如果省略,则会在写入检查中重复使用 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);

使用会话用户和当前用户

PostgreSQL 提供内置函数,用于在策略表达式中识别活动用户:

  • 当前用户 — 当前处于活动状态、其权限正在生效的角色(执行 SET ROLE 后可能发生变化)。
  • 会话用户 — 建立连接的角色(在会话期间不会发生变化)。

大多数 RLS 策略依赖于 当前用户,因为它反映了角色切换后的有效角色。

-- 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(默认) — 所有宽松策略通过 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 属性。反过来,您可以使用 FORCE ROW LEVEL SECURITY 强制所有者遵守 RLS。

-- 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 模式,是在每张表中存储一个租户标识符列,并使用会话级变量在连接时通过 set_config 传递租户标识符。然后,策略会将每一行的租户标识符与该设置进行比较。

-- 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 中行级安全策略的理解。

课程回顾

在本课中,您学习了 Row-Level Security 如何直接在数据库层提供自动的、由策略驱动的行筛选:

  • 使用 ALTER TABLE ... ENABLE ROW LEVEL SECURITY 在表上启用 RLS。
  • 使用 CREATE POLICY 和 USING 子句筛选可读取的行,使用 WITH CHECK 子句验证写入的行。
  • 使用 TO 子句将策略限定到特定命令(SELECT、INSERT、UPDATE、DELETE、ALL)和特定角色。
  • 组合 PERMISSIVE(OR 逻辑)和 RESTRICTIVE(AND 逻辑)策略,实现分层访问控制。
  • 表所有者和超级用户默认绕过 RLS;使用 FORCE ROW LEVEL SECURITY 可覆盖此行为。
  • 使用 current_setting() 的多租户模式,是 RLS 在实际场景中的强大应用。

RLS 是一种标准方式,可以清晰且一致地强制执行数据隔离,而无需将 WHERE 子句分散到每个应用程序查询中。

常见问题解答

「行级安全策略」课时是免费的吗?

是的 — 「行级安全策略」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Academy 课程的其余内容,请升级到 CoddyKit PRO。 SQL Academy 课程共包含 4 节课。

「行级安全策略」这节课中我会学到什么?

自动按用户筛选行 你通过在浏览器中直接运行的动手代码来练习 SQL Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 SQL Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 SQL Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「行级安全策略」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 SQL Academy 课中编写并运行代码吗?

能。每节 SQL Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 角色与权限
  2. 行级安全策略
  3. 列级权限
  4. 审计访问权限
← 返回 SQL Academy