PostgreSQL: PostgreSQL用户、角色与权限管理
最后更新:2026-08-26
1. 你将学到
- CREATE ROLE / CREATE USER(PG 中 USER = LOGIN 角色)
- GRANT / REVOKE 权限管理
- 权限层级:database / schema / table / column / function / sequence
- DEFAULT PRIVILEGES 默认权限
- 行级安全策略(RLS / Row Security Policies,PG 特色)
- SCHEMA 权限控制
- 角色继承(INHERIT / NOINHERIT)
- 系统视图:pg_roles / pg_auth_members
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) 权限层级
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. 流程图:权限配置决策
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 等权限。两层权限必须同时满足。
📖 小节
- PG 中 USER = LOGIN ROLE,角色是权限管理的核心单位
- 角色属性:LOGIN/SUPERUSER/CREATEDB/CREATEROLE/INHERIT 控制不同能力
- GRANT/REVOKE 管理权限,权限层级:database → schema → table → column
- DEFAULT PRIVILEGES 解决新建对象自动授权问题
- RLS(PG 特色)实现行级访问控制,USING 过滤可见行,WITH CHECK 验证新行
- INHERIT 自动继承权限,NOINHERIT 需 SET ROLE 临时提权
- pg_roles / pg_auth_members / information_schema 视图查询权限配置
- 最小权限原则:按需授权,避免过度权限
📝 作业
-
⭐ 创建角色
readonly和用户report_user,授予readonly对 public schema 中所有表的 SELECT 权限,并设置默认权限使新建表也自动授权。 -
⭐⭐ 为
orders表启用 RLS,创建策略:sales_team只能看到自己区域的订单(region = current_setting('app.region')),audit_team只能看到order_status = 'completed'的订单。 -
⭐⭐⭐ 设计一个完整的权限体系:创建 3 个组角色(
backend_dev、data_analyst、db_admin),分别授予不同层级的权限(schema/table/column/function/sequence),配置 DEFAULT PRIVILEGES,为salary列单独授权(analyst 不可见),用pg_roles和information_schema查询验证配置结果。