postgresql中限制用户仅查单表的可靠方式是显式执行grant select on table table_name to user;需配合revoke usage on schema public from public防信息泄露,非public schema还需grant usage on schema。
postgresql 中怎么用 grant 限制用户只查一个表
直接给 select 权限到具体表,不给 schema 或 database 级权限,是唯一可靠方式。postgresql 默认不继承 public schema 的权限,但新手常误以为“没授权就安全”,其实 public schema 下新表默认可能被 public 组读取——得手动关掉。
-
CREATE SCHEMA后立即执行REVOKE USAGE ON SCHEMA public FROM PUBLIC,否则别人能列 schema 下的表名 - 对目标表执行
GRANT SELECT ON TABLE my_table TO limited_user,别漏写TABLE关键字,否则语法错 - 不要给
USAGE权限到 schema,否则用户能\dt看到所有表名(即使查不了内容) - 如果表在非
publicschema(比如app_data),必须同时GRANT USAGE ON SCHEMA app_data TO limited_user,否则连SELECT都报 “relation does not exist”
MySQL 8.0 怎么让账号只能访问 orders 表
MySQL 的表级权限靠 GRANT ... ON database.table 实现,但注意:它不自动包含对 database 的 USAGE,而某些客户端(如 MySQL Workbench)连库时会尝试查 information_schema,导致连接成功但查询报错。
- 执行
GRANT SELECT ON mydb.orders TO 'reporter'@'localhost'即可,不用额外开库权限 - 但若应用执行
USE mydb或依赖information_schema.TABLES,就得补一句GRANT SELECT ON information_schema.TABLES TO 'reporter'@'localhost'(仅当真需要 SHOW TABLES) - MySQL 8.0+ 默认启用
sql_mode = ONLY_FULL_GROUP_BY,如果查询里用了聚合但没写全 GROUP BY 字段,会直接拒绝——这不是权限问题,但容易误判为“权限不够” - 记得
FLUSH PRIVILEGES,尤其从 SQL 文件导入权限后,否则改动不生效
为什么 GRANT SELECT ON ALL TABLES IN SCHEMA 不行
这条命令看起来省事,实际等于把整个 schema 未来建的所有表都提前授权了,违背“单表”前提。而且它不覆盖已存在的权限冲突,更难审计。
-
GRANT SELECT ON ALL TABLES IN SCHEMA public TO u1是一次性快照,后续新建表不会自动授权,除非再跑一遍 - 想长期自动授权,得配
ALTER DEFAULT PRIVILEGES,但它作用于“将来创建的表”,且作用域是 role + schema 组合,配置稍复杂 - 更危险的是:如果误对
ALL TABLES授权后又删表重建,新表仍继承旧权限——你根本意识不到 - 真正可控的做法永远是显式写死表名:
GRANT SELECT ON TABLE logs_202404 TO auditor
验证权限是否真的生效了
别信文档,直接用目标用户连上去试。重点不是“能不能 SELECT”,而是“能不能发现其他表存在”。
- 用该用户登录后执行
\dt(psql)或SHOW TABLES(MySQL),应该只看到被授权的那张表,或干脆报错 - 尝试
SELECT * FROM other_table,确认返回明确权限错误,比如 PostgreSQL 的permission denied for table other_table,而不是模糊的relation does not exist(后者说明 schema 权限没给,或表名拼错) - 如果用 ORM(如 Django、SQLAlchemy),检查它是否默认执行
SELECT pg_tables类语句探库结构——这种行为会暴露未授权表名,得关掉 introspection 或换连接用户
最易忽略的点:权限变更后,有些连接池(如 PgBouncer)或应用层连接复用,会让旧权限缓存几分钟。别急着改代码,先 KILL 对应 backend 进程或重启连接池。










