行级安全策略
自动按用户筛选行
行级安全策略 是 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 反馈 — 无需本地设置。