4 minutes
用户与权限管理
数据库安全的第一道防线是完善的用户和权限管理体系。PostgreSQL 提供了精细的权限控制模型,从数据库级别到列级别都能控制。
用户/角色管理
PostgreSQL 中用户和角色概念相通——区别在于用户默认有 LOGIN 权限,角色没有。
-- 创建用户
CREATE USER alice WITH PASSWORD 'alice123';
-- 等价于 CREATE ROLE alice WITH LOGIN PASSWORD 'alice123';
-- 创建角色(不用于登录,用于权限分组)
CREATE ROLE sales_team;
CREATE ROLE dev_team;
CREATE USER bob WITH PASSWORD 'bob456';
CREATE USER charlie WITH PASSWORD 'charlie789';
修改用户
-- 修改密码
ALTER USER alice WITH PASSWORD 'newpassword';
-- 修改属性
ALTER USER alice WITH SUPERUSER; -- 设为超级用户
ALTER USER alice WITH NOSUPERUSER; -- 取消超级用户
ALTER USER alice WITH CREATEDB; -- 允许创建数据库
ALTER USER alice WITH CREATEROLE; -- 允许创建角色
-- 禁用用户
ALTER USER alice WITH NOLOGIN;
-- 重命名
ALTER USER alice RENAME TO alice_new;
删除用户
-- 删除前确认没有依赖的数据库对象
REASSIGN OWNED BY alice TO postgres; -- 转移对象所有权
DROP OWNED BY alice; -- 删除用户所有的对象
DROP USER alice;
角色继承
角色的核心价值在于层级管理——把权限授予角色,然后把角色授予用户:
-- 创建角色层级
CREATE ROLE readonly NOINHERIT; -- NOINHERIT:不自动继承权限
CREATE ROLE readwrite;
CREATE ROLE admin;
-- 授予角色权限
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO readwrite;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin;
-- 继承关系(admin 继承 readwrite 和 readonly 的权限)
GRANT readonly TO readwrite;
GRANT readwrite TO admin;
-- 授予用户
GRANT readwrite TO bob;
使用 NOINHERIT 的角色需要用 SET ROLE 激活:
-- 设置角色
SET ROLE readonly;
-- 现在拥有 readonly 的权限
SELECT * FROM orders; -- 可以查询
INSERT INTO orders ... VALUES ...; -- ❌ 不可插入
-- 恢复原始用户
RESET ROLE;
对象权限
-- 授予对特定表的查询权限
GRANT SELECT ON orders TO readonly;
GRANT SELECT, INSERT, UPDATE ON orders TO readwrite;
GRANT ALL ON orders TO admin;
-- 授予 schema 的使用权限
GRANT USAGE ON SCHEMA public TO readonly;
GRANT CREATE ON SCHEMA public TO readwrite;
默认权限
对现有表做了 GRANT,但新表怎么办?用 ALTER DEFAULT PRIVILEGES:
-- 当前用户将来创建的所有表,readwrite 组都有 SELECT, INSERT 权限
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO readwrite;
-- 当前用户将来创建的所有函数,readonly 组都有执行权限
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT EXECUTE ON FUNCTIONS TO readonly;
列级权限
-- 敏感列仅对特定角色开放
GRANT SELECT (name, email, department) ON employees TO readonly;
-- 但工资列隐藏
REVOKE SELECT (salary) ON employees FROM readonly;
行级安全(RLS)
PostgreSQL 9.5+ 支持行级安全策略,让不同用户看到不同的数据行:
-- 启用行级安全
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
ALTER TABLE orders FORCE ROW LEVEL SECURITY; -- 对表所有者同样生效
-- 创建策略:每个用户只能看自己的订单
CREATE POLICY user_orders ON orders
FOR SELECT
USING (customer_id = current_setting('myapp.user_id')::INT);
-- 创建策略:用户只能修改自己的订单
CREATE POLICY user_update_orders ON orders
FOR UPDATE
USING (customer_id = current_setting('myapp.user_id')::INT)
WITH CHECK (customer_id = current_setting('myapp.user_id')::INT);
多角色 RLS 示例
-- 数据表带可见性控制
ALTER TABLE documents ADD COLUMN visibility VARCHAR(20) DEFAULT 'private';
ALTER TABLE documents ADD COLUMN owner_id INT;
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
-- 公开文档:所有人可见
CREATE POLICY public_docs ON documents
FOR SELECT
USING (visibility = 'public');
-- 私有文档:仅自己可见
CREATE POLICY own_docs ON documents
FOR SELECT
USING (owner_id = current_setting('app.user_id')::INT);
-- 已提交文档:仅审核组可见
CREATE POLICY reviewed_docs ON documents
FOR SELECT
USING (visibility = 'reviewed' AND
current_role IN ('reviewer', 'admin'));
pg_hba.conf 认证配置
用户能连接数据库不仅取决 SQL 权限,还取决于 pg_hba.conf:
# TYPE DATABASE USER ADDRESS METHOD
local all all scram-sha-256 # 本地连接
host all all 127.0.0.1/32 scram-sha-256 # 本机网络
host all all 192.168.1.0/24 scram-sha-256 # 内网
host all all 0.0.0.0/0 reject # 拒绝外网
认证方法优先级:
| 方法 | 安全性 | 场景 |
|---|---|---|
| trust | 最低 | 开发环境 |
| password | 低 | 密码明文传输 |
| md5 | 中 | 常用,密码哈希 |
| scram-sha-256 | 高 | 推荐,抗暴力破解 |
| cert | 很高 | 客户端证书认证 |
| gssapi | 高 | 企业的 Kerberos 环境 |
权限最佳实践
最小权限原则
-- 创建只读账号用于报表查询
CREATE ROLE report_user LOGIN PASSWORD 'report123';
GRANT CONNECT ON DATABASE mydb TO report_user;
GRANT USAGE ON SCHEMA public TO report_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO report_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO report_user;
审计登录
-- 开启登录审计
ALTER USER alice SET log_login_connections = on; -- 需要超级用户设置
-- 查看 pg_hba.conf 设置后生效
-- 在配置文件中增加:
-- log_connections = on
-- log_disconnections = on
定期检查权限
-- 查看用户的权限
SELECT * FROM information_schema.role_table_grants
WHERE grantee = 'readwrite';
-- 查看当前用户的权限
SELECT * FROM information_schema。applicable_roles;
-- 查看数据库的权限概要
SELECT
grantee,
table_schema,
table_name,
string_agg(privilege_type, ', ' ORDER BY privilege_type) AS privileges
FROM information_schema。role_table_grants
WHERE table_schema = 'public'
GROUP BY grantee, table_schema, table_name
ORDER BY grantee, table_name;
小结
用户和权限管理是数据库安全的核心。PostgreSQL 的权限体系从认证(pg_hba.conf)到角色继承、从对象权限到行级安全(RLS),提供了全方位的分级控制。核心实践:最小权限原则、角色而非直接用户授权、定期审计。
下一篇文章将学习 PostgreSQL 的高级特性——JSON、全文搜索、扩展等。
Summary: 用户角色管理、GRANT 权限、行级安全(RLS)与认证配置。