如何为 Postgresql 中的所有数据库创建具有只读权限的用户?

Posted

技术标签:

【中文标题】如何为 Postgresql 中的所有数据库创建具有只读权限的用户?【英文标题】:How to create a user with readonly privileges for all databases in Postgresql? 【发布时间】:2011-09-21 03:08:03 【问题描述】:

我想为所有数据库中的所有表创建一个只有选择权限的用户。我认为我可以获取数据库列表并为每个数据库应用以下命令:

GRANT select ON DATABASE dbname to user1;

但我收到以下错误:

ERROR:  invalid privilege type SELECT for database

当我在谷歌上搜索时,人们建议对所有表执行 grant select 操作。但是总是在添加新表。所以这对我来说不是一个可以接受的解决方案。有谁知道任何解决方法?

【问题讨论】:

@Jonas 实际上这是基本 SQL,因此不适合 DBA - dba.stackexchange.com/faq 【参考方案1】:

试试:

CREATE USER readonly WITH ENCRYPTED PASSWORD 'yourpassword';
GRANT CONNECT ON DATABASE <database_name> to readonly;
GRANT USAGE ON SCHEMA public to readonly;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;

【讨论】:

【参考方案2】:

我会执行以下步骤来创建只读用户:

创建你的用户:

1. createuser --interactive --pwprompt

转到 your_databases 中的 postgresql:

2. psql your_database                      

定义访问权限:

3. GRANT SELECT ON ALL TABLES IN SCHEMA public TO your_user; 

定义默认访问权限:

4. ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO your_user;

【讨论】:

【参考方案3】:

您不能在数据库级别执行此操作,只能在架构级别执行此操作。

假设您只在每个数据库中使用public 架构,您可以这样做:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO user1;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO user;

【讨论】:

您声明这将应用于新创建的表和视图是不正确的 - “ALL TABLES”只是在每个当前存在的表上运行 GRANT SELECT 的简写,并且没有设置任何默认值.要为新对象设置默认值,您需要 ALTER DEFAULT PRIVILEGES 命令:postgresql.org/docs/current/static/…(请参阅下面的答案) 最初的问题是关于所有表和所有数据库的 SELECT 主题。这在 mysql 中是可能的,但(我认为)在 postgres 中是不可能的。在 postgres 中,必须独立地为每个数据库授予这些权限。也许您可以将其添加为澄清(或在可能的情况下纠正我)。 @Michael:嗯,我认为第一句话“你不能在数据库级别上做到这一点”几乎就是这样说的。您必须按 schema 执行此操作,不能按数据库(或安装范围)执行此操作 是的 - 如果你知道 postgres。我的猜测(对我来说也是如此)是很多对 pg 知识有限的人会发现这个问答。不是每个人都会知道架构是特定于数据库的。另外,如果您只是通过psql 进行连接,则可以发出上述命令而不会出错-> 这使我假设 GRANT 已在安装范围内应用:)。也许只需将psql database_name 添加为第一个命令。另一方面,这些 cmets 对于其他人来说可能就足够了:)【参考方案4】:

对于低于 9.0 的 Postgres 版本:

psql -d DBNAME -qAt -c "SELECT 'GRANT SELECT ON ' || tablename || ' TO USER;' 
FROM pg_tables WHERE schemaname = 'public'" | psql -d DBNAME

psql -d DBNAME -qAt -c "SELECT 'GRANT SELECT ON ' || viewname || ' TO USER;' 
FROM pg_views WHERE schemaname = 'public'" | psql -d DBNAME

psql -d DBNAME -qAt -c "SELECT 'GRANT SELECT ON ' || relname || ' TO USER;' 
FROM pg_statio_all_sequences WHERE schemaname = 'public'" | psql -d DBNAME

【讨论】:

我还得做psql -d DBNAME -qAt -c "SELECT 'GRANT SELECT ON ' || relname || ' TO USER;' FROM pg_statio_all_tables WHERE schemaname = 'public'" | psql -d DBNAME【参考方案5】:

您需要做两件事:首先,允许访问现有对象;其次,为从现在开始创建的新对象设置默认访问权限。

请注意,授予对“TABLES”的访问权限包括视图,但不包括序列(例如“SERIAL”列的自动增量功能),因此您可能也希望授予对这些视图的访问权限。

以下假设您要在 public 架构中执行所有操作。 ALTER DEFAULT PRIVILEGES 语句可以通过省略IN SCHEMA ... 子句作用于整个数据库; GRANT 必须为每个架构运行一次。

-- Grant access to current tables and views
GRANT SELECT ON ALL TABLES IN SCHEMA public TO user1;
-- Now make sure that's also available on new tables and views by default
ALTER DEFAULT PRIVILEGES
    IN SCHEMA public -- omit this line to make a default across all schemas
    GRANT SELECT
ON TABLES 
TO user1;

-- Now do the same for sequences
GRANT SELECT, USAGE ON ALL SEQUENCES IN SCHEMA public TO user1;
ALTER DEFAULT PRIVILEGES
    IN SCHEMA public -- omit this line to make a default across all schemas
    GRANT SELECT, USAGE
ON SEQUENCES 
TO user1;

PostgreSQL 手册

http://www.postgresql.org/docs/current/interactive/sql-grant.html http://www.postgresql.org/docs/current/interactive/sql-alterdefaultprivileges.html

【讨论】:

奇怪的是我也需要grant usage on schema public to user1; 首先连接到正确的数据库很重要\c mydatabase;user1 只能访问mydatabase【参考方案6】:

我知道你已经说过这不是一个可以接受的答案,但无论如何它是正确的答案。

指定安全性(GRANT 和 REVOKE)是表设计和测试的一部分。

在表定义、安全性、测试和测试数据处于版本控制之下之前,不要将表移至生产环境。

话虽如此,PostgreSQL 对数据库没有任何 SELECT 权限。您只能授予对数据库的 CREATE、CONNECT 或 TEMP 权限。

您可以在给定架构中的所有表上授予 SELECT。我不知道这对运行 GRANT 语句后创建的表有何影响,但测试起来相当容易。

PostgreSQL Grant syntax

【讨论】:

以上是关于如何为 Postgresql 中的所有数据库创建具有只读权限的用户?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 postgresql 数组数据类型创建 laravel 迁移

如何为 postgresql MATERIALIZED VIEW 创建 typeorm 实体

如何为 PostgreSQL 中的自链接记录设计最佳实践数据结构?

Postgresql:如何为postgres中的相同时间戳选择“媒体”列中的最大值?

如何为SQL Server数据库中的所有表创建触发器

如何为 oracle 中的每个线程选择和阻止行?(PostgreSQL 有一个工作示例)