PostgreSQL: PostgreSQL用户、角色与权限管理

最后更新:2026-08-26

1. 你将学到


2. 故事

Charlie 是 SaaS 电商平台的 DBA,需要为 5 个团队配置数据库权限:

团队 需要的权限
dev(开发) 读写所有业务表,创建测试表
analytics(分析) 只读所有业务表,创建物化视图
ops(运维) 管理用户、监控数据库
audit(审计) 只能读审计日志,不能读业务数据
app(应用服务) 读写业务表,不能 DDL

Charlie 用角色继承和 RLS 实现最小权限原则。


3. Concept:角色与用户

(1) CREATE ROLE vs CREATE USER

命令 LOGIN 权限 等价写法
CREATE ROLE r1; 无(不能登录)
CREATE USER u1; 有(可登录) CREATE ROLE u1 LOGIN;

PG 中用户和角色是同一概念,USER 只是带 LOGIN 属性的 ROLE。

(2) 角色属性一览

属性 说明 创建语法
LOGIN 允许连接数据库 LOGIN / NOLOGIN
SUPERUSER 超级用户,绕过所有权限 SUPERUSER
CREATEDB 可创建数据库 CREATEDB
CREATEROLE 可创建/管理角色 CREATEROLE
INHERIT 自动继承所属角色的权限 INHERIT(默认)
NOINHERIT 不自动继承,需 SET ROLE NOINHERIT
PASSWORD 设置密码 PASSWORD 'xxx'
VALID UNTIL 密码过期时间 VALID UNTIL 'timestamp'

▶ 示例:创建角色与用户

SQL
-- Group roles (cannot login)
CREATE ROLE dev_team NOINHERIT;
CREATE ROLE analytics_team NOINHERIT;
CREATE ROLE ops_team NOINHERIT;
CREATE ROLE audit_team NOINHERIT;

-- Login users
-- ⚠️ 生产环境不要硬编码密码,应使用环境变量或密钥管理服务
CREATE USER alice_dev PASSWORD 'SecureP@ss1' IN ROLE dev_team;
CREATE USER bob_dev PASSWORD 'SecureP@ss2' IN ROLE dev_team;
CREATE USER charlie_analyst PASSWORD 'SecureP@ss3' IN ROLE analytics_team;
CREATE USER diana_ops PASSWORD 'SecureP@ss4' IN ROLE ops_team INHERIT;

输出:

TEXT 📖 仅展示
CREATE TABLE

▶ 示例:修改角色属性

SQL
-- Add CREATEDB privilege to ops team lead
ALTER ROLE diana_ops CREATEDB;

-- Set password expiry
ALTER ROLE charlie_analyst VALID UNTIL '2025-12-31';

-- Rename a role
ALTER ROLE dev_team RENAME TO engineering_team;

-- Disable login temporarily
ALTER ROLE bob_dev NOLOGIN;

输出:

TEXT 📖 仅展示
CREATE TABLE

4. Concept:GRANT / REVOKE 权限

(1) 权限层级

100%
flowchart TD
    A[Database<br/>CONNECT / CREATE / TEMP] --> B[Schema<br/>CREATE / USAGE]
    B --> C[Table<br/>SELECT / INSERT / UPDATE / DELETE / TRUNCATE / REFERENCES / TRIGGER]
    C --> D[Column<br/>SELECT / INSERT / UPDATE / REFERENCES]
    B --> E[Function<br/>EXECUTE]
    B --> F[Sequence<br/>USAGE / SELECT / UPDATE]
    A --> G[Role<br/>MEMBER / SET]

    style A fill:#e1f5fe
    style B fill:#bbdefb
    style C fill:#c8e6c9
    style D fill:#fff9c4

(2) 常用权限关键字

对象 可授权限 说明
DATABASE CONNECT, CREATE, TEMP 连接、建 schema、临时表
SCHEMA CREATE, USAGE 建对象、访问对象
TABLE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER 全部 CRUD + 外键引用
COLUMN SELECT, INSERT, UPDATE, REFERENCES 列级控制
FUNCTION EXECUTE 调用函数
SEQUENCE USAGE, SELECT, UPDATE 使用序列

▶ 示例:GRANT 表级权限

SQL
-- Dev team: full CRUD on business tables
GRANT SELECT, INSERT, UPDATE, DELETE ON products TO dev_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON orders TO dev_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON customers TO dev_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON order_items TO dev_team;

-- Analytics team: read-only
GRANT SELECT ON products TO analytics_team;
GRANT SELECT ON orders TO analytics_team;
GRANT SELECT ON customers TO analytics_team;

-- Audit team: only audit logs
GRANT SELECT ON price_audit_log TO audit_team;
GRANT SELECT ON ddl_audit_log TO audit_team;

输出:

TEXT 📖 仅展示
INSERT 0 1

▶ 示例:GRANT Schema 与 Database 权限

SQL
-- Dev team can create objects in dev schema
GRANT CREATE, USAGE ON SCHEMA dev TO dev_team;

-- Analytics team can use but not create in public schema
GRANT USAGE ON SCHEMA public TO analytics_team;

-- Allow analytics to create materialized views in their own schema
GRANT CREATE, USAGE ON SCHEMA analytics TO analytics_team;

-- App service connects to the database
GRANT CONNECT ON DATABASE shop_db TO app_service;

输出:

TEXT 📖 仅展示
CREATE TABLE

▶ 示例:REVOKE 撤销权限

SQL
-- Revoke DELETE from dev team on products
REVOKE DELETE ON products FROM dev_team;

-- Revoke all privileges on a table
REVOKE ALL PRIVILEGES ON orders FROM public;

-- Revoke schema creation right
REVOKE CREATE ON SCHEMA dev FROM dev_team;

-- Cascade: revoke and dependent grants
REVOKE SELECT ON products FROM analytics_team CASCADE;

输出:

TEXT 📖 仅展示
DELETE 2

(3) GRANT ALL 与 GRANT SELECT ALL TABLES

命令 效果
GRANT ALL ON t TO r; 授予表 t 的全部权限
GRANT ALL ON SCHEMA s TO r; 授予 schema s 的全部权限
GRANT SELECT ON ALL TABLES IN SCHEMA s TO r; 授予 schema s 中所有表的 SELECT
GRANT USAGE ON ALL SEQUENCES IN SCHEMA s TO r; 授予所有序列的 USAGE

5. Concept:DEFAULT PRIVILEGES

(1) 为什么需要默认权限

普通 GRANT 只影响已存在的对象。未来新建的表不会自动获得权限。DEFAULT PRIVILEGES 解决这个问题。

命令 效果
ALTER DEFAULT PRIVILEGES IN SCHEMA s GRANT SELECT ON TABLES TO r; s 中新建表自动授权
ALTER DEFAULT PRIVILEGES FOR ROLE owner GRANT ... 指定创建者的默认权限

▶ 示例:设置默认权限

SQL
-- All future tables in public schema are readable by analytics_team
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO analytics_team;

-- All future tables created by app_service are writable by dev_team
ALTER DEFAULT PRIVILEGES FOR ROLE app_service IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE ON TABLES TO dev_team;

-- All future sequences in public schema
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT USAGE, SELECT ON SEQUENCES TO dev_team;

-- All future functions
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT EXECUTE ON FUNCTIONS TO analytics_team;

输出:

TEXT 📖 仅展示
INSERT 0 1

▶ 示例:查看当前默认权限

SQL
SELECT
  pg_get_userbyid(defaclrole) AS grantor,
  pg_get_userbyid(defaclnamespace) AS namespace_owner,
  n.nspname AS schema,
  defaclobjtype AS object_type,
  defaclacl AS acl
FROM pg_default_acl d
JOIN pg_namespace n ON n.oid = d.defaclnamespace;

输出:

TEXT 📖 仅展示
 id | name     | value 
----+----------+-------
  1 | example  | 42
(1 row)

6. Concept:行级安全策略(RLS)

(1) RLS 工作原理(PG 特色)

RLS 允许在行级别控制数据访问——同一张表不同角色只能看到不同的行。

步骤 命令 说明
1. 启用 RLS ALTER TABLE t ENABLE ROW LEVEL SECURITY; 表上开启行级安全
2. 创建策略 CREATE POLICY ... ON t ...; 定义行级规则
3. 超级用户绕过 SUPERUSER 默认不受 RLS 限制
4. 表所有者绕过 表 owner 默认不受限制,需 FORCE 强制

(2) 策略类型

策略类型 命令关键词 说明
SELECT FOR SELECT 控制可见行
INSERT FOR INSERT 控制可插入行
UPDATE FOR UPDATE 控制可更新行(含 BEFORE/AFTER)
DELETE FOR DELETE 控制可删除行
ALL FOR ALL 所有操作共用

▶ 示例:启用 RLS 并创建策略

SQL
-- Enable RLS on orders table
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

-- Analysts can only see completed orders
CREATE POLICY pol_analytics_completed
  ON orders FOR SELECT
  TO analytics_team
  USING (order_status = 'completed');

-- Dev team can see all rows
CREATE POLICY pol_dev_all
  ON orders FOR ALL
  TO dev_team
  USING (true)
  WITH CHECK (true);

输出:

TEXT 📖 仅展示
CREATE TABLE

▶ 示例:基于当前用户的 RLS

SQL
-- Enable RLS on customers table
ALTER TABLE customers ENABLE ROW LEVEL SECURITY;

-- Each customer service user sees only their assigned region
CREATE POLICY pol_region_access
  ON customers FOR SELECT
  USING (region = current_setting('app.region', true));

-- Force table owner to also comply with RLS
ALTER TABLE orders FORCE ROW LEVEL SECURITY;

输出:

TEXT 📖 仅展示
CREATE TABLE

▶ 示例:INSERT/UPDATE 的 WITH CHECK

SQL
-- Sales team can only insert orders in their region
CREATE POLICY pol_sales_insert
  ON orders FOR INSERT
  TO dev_team
  WITH CHECK (region = current_setting('app.region', true));

-- Sales team can only update orders in their region
CREATE POLICY pol_sales_update
  ON orders FOR UPDATE
  TO dev_team
  USING (region = current_setting('app.region', true))
  WITH CHECK (region = current_setting('app.region', true));

输出:

TEXT 📖 仅展示
INSERT 0 1

(3) USING vs WITH CHECK

子句 作用 适用操作
USING 过滤可见行(SELECT/UPDATE/DELETE 的 WHERE) SELECT/UPDATE/DELETE
WITH CHECK 验证新行是否允许(INSERT/UPDATE 的新值) INSERT/UPDATE

7. Concept:角色继承与系统视图

(1) INHERIT vs NOINHERIT

属性 行为 场景
INHERIT(默认) 自动获得所属角色的权限 普通用户
NOINHERIT SET ROLE r 才能使用权限 临时提权、审计分离

▶ 示例:NOINHERIT 与 SET ROLE

SQL
-- Create a powerful role with NOINHERIT
CREATE ROLE admin_role NOINHERIT;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin_role;

-- Diana is in admin_role but cannot use admin privileges automatically
CREATE USER diana PASSWORD 'SecureP@ss5' IN ROLE admin_role NOINHERIT;

-- Diana must explicitly switch to use admin rights
SET ROLE admin_role;
-- Now diana can perform admin operations
RESET ROLE;
-- Back to normal privileges

输出:

TEXT 📖 仅展示
CREATE TABLE

(2) 系统视图

视图 内容
pg_roles 所有角色及其属性
pg_auth_members 角色-成员关系
information_schema.role_table_grants 表级权限
information_schema.role_usage_grants Schema/函数权限

▶ 示例:查询角色与权限

SQL
-- List all roles and their attributes
SELECT rolname, rolsuper, rolcreatedb, rolcanlogin, rolinherit
FROM pg_roles
WHERE rolname NOT LIKE 'pg_%'
ORDER BY rolname;

-- List role membership
SELECT
  r1.rolname AS member,
  r2.rolname AS role
FROM pg_auth_members m
JOIN pg_roles r1 ON r1.oid = m.member
JOIN pg_roles r2 ON r2.oid = m.roleid
ORDER BY r2.rolname, r1.rolname;

-- Check table privileges for a role
SELECT table_name, privilege_type
FROM information_schema.role_table_grants
WHERE grantee = 'analytics_team'
ORDER BY table_name, privilege_type;

输出:

TEXT 📖 仅展示
CREATE TABLE

8. 流程图:权限配置决策

100%
flowchart TD
    A[配置权限] --> B{需要行级控制?}
    B -->|是| C[启用 RLS<br/>CREATE POLICY]
    B -->|否| D{权限粒度?}
    D -->|整表| E[GRANT ON TABLE]
    D -->|特定列| F[GRANT column_name ON TABLE]
    D -->|Schema内所有表| G[GRANT ALL TABLES IN SCHEMA]
    E --> H{需要自动授权新表?}
    G --> H
    H -->|是| I[ALTER DEFAULT PRIVILEGES]
    H -->|否| J[手动 GRANT]
    C --> K{表 owner 也需限制?}
    K -->|是| L[FORCE ROW LEVEL SECURITY]
    K -->|否| M[默认 owner 绕过 RLS]
    I --> N{用户需临时提权?}
    J --> N
    N -->|是| O[NOINHERIT + SET ROLE]
    N -->|否| P[INHERIT 默认]

    style C fill:#fff9c4
    style I fill:#c8e6c9
    style O fill:#ffcdd2

9. 综合示例

Charlie 为 5 个团队配置完整权限体系:

SQL
-- Step 1: Create group roles
CREATE ROLE dev_team NOINHERIT;
CREATE ROLE analytics_team NOINHERIT;
CREATE ROLE ops_team INHERIT;
CREATE ROLE audit_team NOINHERIT;
CREATE ROLE app_service LOGIN PASSWORD 'AppSecRet!';

-- Step 2: Grant schema permissions
GRANT CREATE, USAGE ON SCHEMA public TO dev_team;
GRANT USAGE ON SCHEMA public TO analytics_team;
GRANT CREATE, USAGE ON SCHEMA analytics TO analytics_team;
GRANT USAGE ON SCHEMA public TO ops_team;
GRANT USAGE ON SCHEMA audit TO audit_team;

-- Step 3: Grant table permissions
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO dev_team;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO analytics_team;
GRANT SELECT ON ALL TABLES IN SCHEMA audit TO audit_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON products, orders, order_items, customers TO app_service;

-- Step 4: Default privileges for future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO analytics_team;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO dev_team;
ALTER DEFAULT PRIVILEGES IN SCHEMA audit
  GRANT SELECT ON TABLES TO audit_team;

-- Step 5: Sequence and function permissions
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO dev_team;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_service;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT USAGE, SELECT ON SEQUENCES TO dev_team;

-- Step 6: RLS - analysts only see completed orders
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY pol_analytics_orders
  ON orders FOR SELECT
  TO analytics_team
  USING (order_status = 'completed');

-- Step 7: RLS - audit team only sees audit schema
ALTER TABLE price_audit_log ENABLE ROW LEVEL SECURITY;
CREATE POLICY pol_audit_read
  ON price_audit_log FOR SELECT
  TO audit_team
  USING (true);

-- Step 8: Create login users and assign roles
CREATE USER alice_dev PASSWORD 'DevP@ss1' IN ROLE dev_team;
CREATE USER bob_dev PASSWORD 'DevP@ss2' IN ROLE dev_team;
CREATE USER charlie_analyst PASSWORD 'AnlP@ss3' IN ROLE analytics_team;
CREATE USER diana_ops PASSWORD 'OpsP@ss4' IN ROLE ops_team CREATEROLE;
CREATE USER eve_audit PASSWORD 'AudP@ss5' IN ROLE audit_team;

❓ 常见问题

Q CREATE USER 和 CREATE ROLE 有什么区别?
A CREATE USER 等价于 CREATE ROLE ... LOGIN。PG 中用户和角色是同一概念,USER 只是默认带 LOGIN 属性的角色。
Q GRANT SELECT ON ALL TABLES 包含未来新建的表吗?
A 不包含。ALL TABLES 只授权给当前存在的表。未来新建表需要 ALTER DEFAULT PRIVILEGES 自动授权或手动 GRANT。
Q RLS 对超级用户有效吗?
A 默认无效。SUPERUSER 绕过所有 RLS 策略。如需强制,用 ALTER TABLE ... FORCE ROW LEVEL SECURITY,但这只对表 owner 生效,SUPERUSER 仍绕过。
Q NOINHERIT 角色如何临时获取权限?
A 用 SET ROLE target_role 切换到目标角色获取其权限,操作完成后 RESET ROLE 恢复原始权限。SET ROLE 仅影响当前会话。
Q REVOKE 需要 CASCADE 吗?
A 如果被撤销的权限又被授权给其他角色(依赖授权),需要 CASCADE 才能一并撤销。默认 RESTRICT 会在有依赖时报错。
Q 如何查看某个用户实际拥有哪些权限?
A 查询 information_schema.role_table_grants 视图,或用 psql 的 \dp 和 \du+ 命令。注意 INHERIT 角色会自动获得所属角色的权限。
Q RLS 的 USING 和 WITH CHECK 可以只写一个吗?
A 可以。如果只写 USING,则 WITH CHECK 默认与 USING 相同。对于 ALL 策略建议显式写两者以明确控制。
Q Schema 的 USAGE 权限不够访问表怎么办?
A USAGE 只允许"进入" schema 查看对象列表,还需在具体表上有 SELECT 等权限。两层权限必须同时满足。

📖 小节


📝 作业

  1. ⭐ 创建角色 readonly 和用户 report_user,授予 readonly 对 public schema 中所有表的 SELECT 权限,并设置默认权限使新建表也自动授权。

  2. ⭐⭐ 为 orders 表启用 RLS,创建策略:sales_team 只能看到自己区域的订单(region = current_setting('app.region')),audit_team 只能看到 order_status = 'completed' 的订单。

  3. ⭐⭐⭐ 设计一个完整的权限体系:创建 3 个组角色(backend_devdata_analystdb_admin),分别授予不同层级的权限(schema/table/column/function/sequence),配置 DEFAULT PRIVILEGES,为 salary 列单独授权(analyst 不可见),用 pg_rolesinformation_schema 查询验证配置结果。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏