外观
PostgreSQL 角色与权限模型
核心概念
PostgreSQL的角色与权限模型基于以下核心概念:
- 角色:用于管理数据库访问权限的实体,可以是用户或组
- 权限:控制角色对数据库对象的操作能力
- 继承:角色可以继承其他角色的权限
- 对象权限:针对表、视图、函数等具体对象的权限
- 系统权限:针对数据库系统级别的权限
- 默认权限:新创建对象时自动应用的权限
角色管理
创建与删除角色
sql
-- 创建普通用户角色
CREATE ROLE app_user WITH LOGIN PASSWORD 'secure_password';
-- 创建管理员角色
CREATE ROLE db_admin WITH SUPERUSER CREATEDB CREATEROLE LOGIN PASSWORD 'admin_password';
-- 创建组角色(无登录权限)
CREATE ROLE read_only_group;
-- 删除角色
DROP ROLE IF EXISTS old_user;角色属性管理
sql
-- 修改角色属性
ALTER ROLE app_user WITH NOSUPERUSER NOCREATEDB NOCREATEROLE;
-- 修改角色密码
ALTER ROLE app_user WITH PASSWORD 'new_secure_password';
-- 锁定/解锁角色
ALTER ROLE app_user WITH NOLOGIN;
ALTER ROLE app_user WITH LOGIN;
-- 设置角色有效期
ALTER ROLE app_user WITH VALID UNTIL '2025-12-31';角色继承与成员关系
sql
-- 将用户添加到组
GRANT read_only_group TO app_user;
-- 从组中移除用户
REVOKE read_only_group FROM app_user;
-- 设置角色继承(PostgreSQL 10+)
ALTER ROLE app_user INHERIT;
-- 查看角色成员关系
SELECT * FROM pg_auth_members;权限管理
对象权限授予与回收
sql
-- 授予表的SELECT权限
GRANT SELECT ON TABLE public.orders TO read_only_group;
-- 授予表的所有权限
GRANT ALL PRIVILEGES ON TABLE public.orders TO db_admin;
-- 授予模式下所有表的SELECT权限
GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only_group;
-- 回收权限
REVOKE INSERT, UPDATE ON TABLE public.orders FROM app_user;默认权限设置
sql
-- 设置新创建表的默认权限
ALTER DEFAULT PRIVILEGES FOR ROLE db_admin IN SCHEMA public
GRANT SELECT ON TABLES TO read_only_group;
-- 设置新创建序列的默认权限
ALTER DEFAULT PRIVILEGES FOR ROLE db_admin IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO app_user;系统权限管理
sql
-- 授予创建数据库权限
GRANT CREATEDB TO app_admin;
-- 授予创建角色权限
GRANT CREATEROLE TO app_admin;
-- 授予超级用户权限(谨慎使用)
ALTER ROLE app_admin WITH SUPERUSER;
-- 查看角色权限
\du+ app_admin;生产环境最佳实践
最小权限原则
- 为每个应用分配独立的角色,避免共享角色
- 只授予角色完成工作所需的最小权限
- 定期审查和回收不必要的权限
- 使用组角色管理权限,简化权限维护
角色分层设计
sql
-- 设计示例:分层角色结构
-- 1. 基础组角色
CREATE ROLE base_role;
GRANT CONNECT ON DATABASE mydb TO base_role;
GRANT USAGE ON SCHEMA public TO base_role;
-- 2. 只读组角色
CREATE ROLE read_role IN ROLE base_role;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_role;
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES TO read_role;
-- 3. 读写组角色
CREATE ROLE write_role IN ROLE read_role;
GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO write_role;
ALTER DEFAULT PRIVILEGES GRANT INSERT, UPDATE, DELETE ON TABLES TO write_role;
-- 4. 应用角色
CREATE ROLE myapp_role IN ROLE write_role LOGIN PASSWORD 'app_password';权限审计与监控
sql
-- 查看角色权限分配
SELECT grantee, privilege_type, table_name
FROM information_schema.role_table_grants
WHERE table_schema = 'public';
-- 查看当前用户权限
SELECT * FROM session_roles;
-- 启用权限审计日志
ALTER SYSTEM SET log_connections = 'on';
ALTER SYSTEM SET log_disconnections = 'on';
ALTER SYSTEM SET log_statement = 'ddl';
SELECT pg_reload_conf();版本差异考虑
- PostgreSQL 10+:引入了更灵活的角色继承机制
- PostgreSQL 11+:增强了默认权限管理
- PostgreSQL 12+:改进了权限检查性能
- PostgreSQL 14+:添加了更细粒度的权限控制选项
常见问题(FAQ)
Q1:如何查看角色的所有权限?
A1:可以使用以下方法查看角色权限:
sql
-- 使用psql元命令
\du+ 角色名;
-- 查询系统表
SELECT r.rolname, r.rolsuper, r.rolcreaterole, r.rolcreatedb,
r.rolinherit, r.rolcanlogin
FROM pg_roles r
WHERE r.rolname = '角色名';
-- 查看对象权限
SELECT grantee, privilege_type, table_name
FROM information_schema.role_table_grants
WHERE grantee = '角色名';Q2:如何实现行级权限控制?
A2:可以使用行级安全性(RLS)实现行级权限控制:
sql
-- 启用行级安全性
ALTER TABLE employees ENABLE ROW LEVEL SECURITY;
-- 创建策略:只允许查看自己部门的员工
CREATE POLICY emp_dept_policy ON employees
FOR SELECT
USING (department_id = current_setting('app.current_dept')::integer);
-- 应用角色设置
CREATE ROLE hr_user WITH LOGIN;
GRANT SELECT ON employees TO hr_user;Q3:如何处理权限继承不生效的问题?
A3:检查以下几点:
- 确认角色设置了INHERIT属性:
ALTER ROLE 角色名 INHERIT; - 确认使用了正确的权限授予语法:
GRANT 组角色 TO 用户角色; - 检查PostgreSQL版本,确保支持角色继承
- 确认没有使用NOINHERIT属性限制
Q4:如何批量管理角色权限?
A4:可以使用以下方法批量管理权限:
sql
-- 批量授予模式下所有表的权限
GRANT SELECT ON ALL TABLES IN SCHEMA public TO 角色名;
-- 使用脚本批量处理
DO $$
DECLARE
r RECORD;
BEGIN
FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' LOOP
EXECUTE format('GRANT SELECT ON TABLE public.%I TO read_only_group', r.tablename);
END LOOP;
END$$;Q5:如何安全地撤销超级用户权限?
A5:按以下步骤操作:
- 创建一个新的管理员角色,只授予必要的权限
- 测试新角色的功能是否正常
- 将原超级用户的权限转移到新角色
- 撤销原超级用户的超级权限:
ALTER ROLE 原角色名 WITH NOSUPERUSER; - 监控系统运行情况,确保没有问题
