如何创建仅可连接并查看单个指定PostgreSQL数据库的用户?
完全可以实现仅允许用户访问单个指定PostgreSQL数据库、且限制其库内表可见范围的需求,你遇到的问题是PostgreSQL默认的PUBLIC角色全局权限导致的,可按以下步骤配置:
步骤1:收回全局默认的PUBLIC连接权限
默认所有用户都会继承PUBLIC角色的权限,而PUBLIC默认拥有所有数据库的连接权限,需要先收回非目标数据库的该权限。使用超级用户执行以下SQL,将[其他数据库名]替换为你实例中除开目标数据库db之外的所有数据库名即可:
REVOKE CONNECT ON DATABASE [其他数据库名1], [其他数据库名2], postgres, template0, template1 FROM PUBLIC;
执行完成后,只有单独授予了CONNECT权限的用户才能连接对应数据库。
步骤2:限制用户查看数据库列表的权限
用户能看到所有数据库名称,是因为PUBLIC默认拥有pg_catalog.pg_database系统表的查询权限,可通过以下两种方案限制:
方案A:调整系统表查询权限(操作简单)
-- 先收回PUBLIC的pg_database全表查询权限 REVOKE SELECT ON pg_catalog.pg_database FROM PUBLIC; -- 给管理员角色保留查询所有数据库的权限,默认管理员为postgres GRANT SELECT ON pg_catalog.pg_database TO postgres; -- 创建权限判断函数 CREATE OR REPLACE FUNCTION pg_catalog.pg_database_is_visible(oid) RETURNS boolean AS $$ SELECT has_database_privilege($1, 'CONNECT'); $$ LANGUAGE sql STABLE SECURITY DEFINER; -- 给普通用户开放过滤后的查询权限,仅能看到自己有权限连接的数据库 GRANT SELECT (datname, datdba, encoding, datcollate, datctype, datistemplate, datallowconn, datconnlimit, datlastsysoid, datfrozenxid, datminmxid, dattablespace, datacl) ON pg_catalog.pg_database TO PUBLIC WHERE pg_catalog.pg_database_is_visible(oid);
方案B:使用行级安全策略(更灵活)
切换到postgres数据库执行以下SQL:
-- 对系统表启用行级安全 ALTER TABLE pg_catalog.pg_database ENABLE ROW LEVEL SECURITY; -- 创建策略仅允许用户查看自己有连接权限的数据库 CREATE POLICY allow_see_own_dbs ON pg_catalog.pg_database FOR SELECT USING (has_database_privilege(oid, 'CONNECT')); -- 给管理员豁免行级安全限制 ALTER ROLE postgres BYPASSRLS;
步骤3:配置目标库内的表可见权限
完成前两步后,用户只能看到并连接目标数据库db,按需配置库内表权限即可:
-- 切换到目标数据库db执行 -- 收回PUBLIC对默认public schema的默认权限 REVOKE ALL ON SCHEMA public FROM PUBLIC; -- 给指定用户开放schema访问权限 GRANT USAGE ON SCHEMA public TO "user"; -- 示例1:给用户开放所有表的只读权限 GRANT SELECT ON ALL TABLES IN SCHEMA public TO "user"; -- 可选:未来新建的表自动授予只读权限 ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO "user"; -- 示例2:仅给用户开放指定表的只读权限 -- GRANT SELECT ON table1, table2 IN SCHEMA public TO "user";
内容的提问来源于stack exchange,提问作者Sebastian Dziedzic
相关产品推荐
相关产品推荐

