PostgreSQL只读用户可创建临时表:原因排查与解决咨询
为什么只读用户还能创建临时表?怎么解决?
问题根源
PostgreSQL里有个很容易被忽略的默认权限规则:所有新建角色默认会继承public角色的权限,而public角色默认拥有数据库的TEMP(临时表创建)权限。你之前的操作里,只撤销了postgres角色的TEMP权限,既没处理public的TEMP权限,也没直接限制read_access的相关权限,所以这个只读用户依然能通过继承public的权限创建临时表。
另外要注意:临时表是在会话专属的pg_temp模式中创建的,只要用户拥有数据库的TEMP权限,就自动获得对自己会话pg_temp模式的CREATE权限——这也是为什么你之前针对public Schema的REVOKE CREATE操作没拦住它的原因。
解决步骤
1. 先确认当前权限状态(可选但推荐)
执行以下命令查看read_access的角色属性:SELECT rolname, rolcanlogin, rolcreaterole, rolcreatedb, rolsuper, rolreplication, rolbypassrls FROM pg_roles WHERE rolname = 'read_access';再查看目标数据库的TEMP权限分配:
SELECT grantee, privilege_type FROM information_schema.table_privileges WHERE table_catalog = '你的数据库名' AND privilege_type = 'TEMPORARY';2. 撤销
read_access的TEMP权限
直接针对这个用户撤销数据库的临时表创建权限:REVOKE TEMP ON DATABASE 你的数据库名 FROM read_access;3. (可选)彻底限制所有普通用户的TEMP权限
如果你的数据库里不需要其他普通用户创建临时表,可以直接撤销public角色的TEMP权限,这样所有继承public的角色都会失去这个权限:REVOKE TEMP ON DATABASE 你的数据库名 FROM public;4. 验证效果
切换到read_access用户,尝试创建临时表:CREATE TEMP TABLE test_temp (id int);如果权限设置正确,会收到类似
ERROR: permission denied to create temporary table的报错,说明限制生效了。
补充说明
- 如果你之后新建其他角色,记得要么单独撤销它们的TEMP权限,要么保持
public的TEMP权限被撤销状态,避免重复踩坑。 - 临时表的权限控制只和数据库级的
TEMP权限有关,和Schema级的CREATE权限无关,所以之前针对publicSchema的权限设置不会影响临时表的创建逻辑。
内容的提问来源于stack exchange,提问作者purplefloyd




