如何在 PostgreSQL 中创建只读用户?

Posted

技术标签:

【中文标题】如何在 PostgreSQL 中创建只读用户?【英文标题】:How do you create a read-only user in PostgreSQL? 【发布时间】:2010-10-20 02:24:39 【问题描述】:

我想在 PostgreSQL 中创建一个只能从特定数据库执行 SELECT 的用户。在 mysql 中,命令是:

GRANT SELECT ON mydb.* TO 'xxx'@'%' IDENTIFIED BY 'yyy';

PostgreSQL 中等价的命令或命令系列是什么?

我试过了……

postgres=# CREATE ROLE xxx LOGIN PASSWORD 'yyy';
postgres=# GRANT SELECT ON DATABASE mydb TO xxx;

但您似乎只能在数据库上授予 CREATE、CONNECT、TEMPORARY 和 TEMP。

【问题讨论】:

【参考方案1】:

将使用/选择授予单个表

如果您只将 CONNECT 授予数据库,则用户可以连接但没有其他权限。您必须在命名空间(模式)上授予 USAGE 并在表和视图上分别授予 SELECT ,如下所示:

GRANT CONNECT ON DATABASE mydb TO xxx;
-- This assumes you're actually connected to mydb..
GRANT USAGE ON SCHEMA public TO xxx;
GRANT SELECT ON mytable TO xxx;

多个表/视图(PostgreSQL 9.0+)

在最新版本的 PostgreSQL 中,您可以使用单个命令授予架构中所有表/视图/等的权限,而不必一一键入:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;

这只影响已经创建的表。更强大的是,你以后可以自动拥有default roles assigned to new objects:

ALTER DEFAULT PRIVILEGES IN SCHEMA public
   GRANT SELECT ON TABLES TO xxx;

请注意,默认情况下,这只会影响发出此命令的用户创建的对象(表):尽管它也可以设置在发出用户所属的任何角色上。但是,在创建新对象时,您不会为您所属的所有角色选择默认权限......所以仍然存在一些问题。如果您采用数据库具有拥有角色的方法,并且架构更改是作为该拥有角色执行的,那么您应该将默认权限分配给该拥有角色。恕我直言,这有点令人困惑,您可能需要进行试验才能提出功能性工作流程。

多个表/视图(PostgreSQL 9.0 之前的版本)

为避免在冗长的多表更改中出错,建议使用以下“自动”流程为每个表/视图生成所需的GRANT SELECT

SELECT 'GRANT SELECT ON ' || relname || ' TO xxx;'
FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE nspname = 'public' AND relkind IN ('r', 'v', 'S');

这应该将相关的 GRANT 命令输出到公开的所有表、视图和序列上的 GRANT SELECT,以便进行复制粘贴。当然,这只会应用于已经创建的表。

【讨论】:

你应该把你对 PG9 的编辑放在帖子的顶部。 不错。我要补充的一件事是,您可能还需要允许该用户读取序列;所以:GRANT SELECT ON SCHEMA public TO xxx 中的所有序列; 请注意,为了防止该用户能够创建新表,我必须REVOKE CREATE ON SCHEMA public FROM PUBLIC;。否则,“只读”用户无法修改现有表,但可以在架构中创建新表并从这些表中添加/删除数据。 @Ajedi32 这应该是已接受答案的一部分!谢谢 对于像我这样的新手,我认为值得一提的是,您应该使用psql mydb 启动控制台,否则大多数这些操作都不会起作用。我个人花了相当多的时间才自己弄清楚。希望这对某人有所帮助。【参考方案2】:

Reference taken from this blog:

创建只读用户的脚本:

CREATE ROLE Read_Only_User WITH LOGIN PASSWORD 'Test1234' 
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION VALID UNTIL 'infinity';

为该只读用户分配权限:

GRANT CONNECT ON DATABASE YourDatabaseName TO Read_Only_User;
GRANT USAGE ON SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO Read_Only_User;

分配权限以读取将来创建的所有新表

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User;

【讨论】:

这是一个非常好的答案,除了缺少一件事:ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User; 这还允许读取将来在同一数据库中创建的所有表。 允许只读用户访问序列是不寻常的。读取序列会更新它,它们通常只需要INSERTs。 为了完整起见,可能添加:GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA schema_name TO Read_Only_User; @jpmc26:是不是意味着你推荐:GRANT ALL ON ALL SEQUENCES IN SCHEMA schema_name TO Read_Only_User 重要的是要指出,从GRANT USAGE... 开始的指令(如对表的 GRANT 权限)应该在所需的数据库中运行,否则权限将不起作用。为此,您可以\connect db_name; 连接到数据库(也可以在sql文件中使用)。【参考方案3】:

请注意,PostgreSQL 9.0(今天处于 beta 测试阶段)将有一个 simple way to do that:

test=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO joeuser;

【讨论】:

我必须在特定的数据库中才能工作。 Postgresql 9.5. 这仅适用于架构中的现有表。如果 write-user 稍后创建或替换表,readonly 用户将无权访问它们【参考方案4】:

这是我发现的添加只读用户(使用 PostgreSQL 9.0 或更高版本)的最佳方法:

$ sudo -upostgres psql postgres
postgres=# CREATE ROLE readonly WITH LOGIN ENCRYPTED PASSWORD '<USE_A_NICE_STRONG_PASSWORD_PLEASE';
postgres=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;

然后登录所有相关机器(master + read-slave(s)/hot-standby(s)等)并运行:

$ echo "hostssl <PUT_DBNAME_HERE> <PUT_READONLY_USERNAME_HERE> 0.0.0.0/0 md5" | sudo tee -a /etc/postgresql/9.2/main/pg_hba.conf
$ sudo service postgresql reload

【讨论】:

我喜欢这种方法,但我还需要 GRANT CONNECT ON DATABASE [thedatabase] TO [theuser or role];和 GRANT USAGE ON SCHEMA public TO [theuser or role]; 公共模式仍然允许这样的用户创建表。此外,未涵盖新表和序列。不幸的是,这一切都比这复杂得多。 :-/ 再次验证后,我将发布我最终所做的事情。 在上面的脚本中,您尝试创建角色两次。我怀疑您在启用登录角色和设置密码时打算使用“ALTER ROLE ...” 如果您已经拥有用户,在创建只读角色并授予选择权限后,将新角色授予用户:GRANT readonly TO 【参考方案5】:

默认情况下,新用户将有权创建表。如果您打算创建一个只读用户,这可能不是您想要的。

要使用 PostgreSQL 9.0+ 创建真正的只读用户,请运行以下步骤:

# This will prevent default users from creating tables
REVOKE CREATE ON SCHEMA public FROM public;

# If you want to grant a write user permission to create tables
# note that superusers will always be able to create tables anyway
GRANT CREATE ON SCHEMA public to writeuser;

# Now create the read-only user
CREATE ROLE readonlyuser WITH LOGIN ENCRYPTED PASSWORD 'strongpassword';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonlyuser;

如果您的只读用户没有列出表的权限(即\d 不返回任何结果),可能是因为您没有架构的USAGE 权限。 USAGE 是一种允许用户实际使用已分配的权限的权限。这有什么意义?我不知道。修复:

# You can either grant USAGE to everyone
GRANT USAGE ON SCHEMA public TO public;

# Or grant it just to your read only user
GRANT USAGE ON SCHEMA public TO readonlyuser;

【讨论】:

【参考方案6】:

从 PostgreSQL v14 开始,您只需授予预定义的 pg_read_all_data 角色即可:

GRANT pg_read_all_data TO xxx;

【讨论】:

【参考方案7】:

我为此创建了一个方便的脚本; pg_grant_read_to_db.sh。此脚本授予指定角色对数据库模式中所有表、视图和序列的只读权限,并将它们设置为默认值。

【讨论】:

非常有用,谢谢。【参考方案8】:

我阅读了所有可能的解决方案,一切都很好,如果你记得在授予东西之前连接到数据库;)无论如何感谢所有其他解决方案!!!

user@server:~$ sudo su - postgres

创建 psql 用户:

postgres@server:~$ createuser --interactive 
Enter name of role to add: readonly
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n

启动 psql cli 并为创建的用户设置密码:

postgres@server:~$ psql
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
Type "help" for help.

postgres=# alter user readonly with password 'readonly';
ALTER ROLE

连接目标数据库:

postgres=# \c target_database 
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
You are now connected to database "target_database" as user "postgres".

授予所有需要的权限:

target_database=# GRANT CONNECT ON DATABASE target_database TO readonly;
GRANT

target_database=# GRANT USAGE ON SCHEMA public TO readonly ;
GRANT

target_database=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly ;
GRANT

更改目标 db public shema 的默认权限:

target_database=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
ALTER DEFAULT PRIVILEGES

【讨论】:

【参考方案9】:

如果您的数据库在公共架构中,这很容易(假设您已经创建了readonlyuser

db=> GRANT SELECT ON ALL TABLES IN SCHEMA public to readonlyuser;
GRANT
db=> GRANT CONNECT ON DATABASE mydatabase to readonlyuser;
GRANT
db=> GRANT SELECT ON ALL SEQUENCES IN SCHEMA public to readonlyuser;
GRANT

如果您的数据库使用customschema,请执行上述但添加一个命令:

db=> ALTER USER readonlyuser SET search_path=customschema, public;
ALTER ROLE

【讨论】:

【参考方案10】:

不直接的方法是在数据库的每个表上授予选择:

postgres=# grant select on db_name.table_name to read_only_user;

您可以通过从数据库元数据生成授权语句来自动执行此操作。

【讨论】:

【参考方案11】:

取自回复despesz'链接的链接。

Postgres 9.x 似乎有能力做所要求的事情。请参阅授予数据库对象的段落:

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

它说:“还有一个选项可以授予对一个或多个模式中相同类型的所有对象的权限。此功能目前仅支持表、序列和函数(但请注意,所有表都被视为包括视图和外部表)。”

此页面还讨论了 ROLE 和称为“ALL PRIVILEGES”的 PRIVILEGE 的使用。

还提供了有关 GRANT 功能与 SQL 标准比较的信息。

【讨论】:

【参考方案12】:
CREATE USER username SUPERUSER  password 'userpass';
ALTER USER username set default_transaction_read_only = on;

【讨论】:

这是一个巨大的安全风险。用户发出的第一条命令只需:set transaction_read_only = off; 拉吉德是对的。请不要在任何数据库上运行此命令,始终至少将“用户名”更改为其他名称,并将“用户密码”更改为安全的名称。

以上是关于如何在 PostgreSQL 中创建只读用户?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 postgresql 中创建只读视图,类似于 oracle?

创建 PostgreSQL 只读用户错误:关系 _foo 的权限被拒绝

在 Elastic Beanstalk Postgresql 中创建 Django 超级用户

在 Postgresql 中创建基于角色的身份验证系统

如何使用 init.sql 在 Postgresql 中创建数据库、模式和表

如何使用 PostgreSQL 在 DBeaver 中创建自动递增/SERIAL id 列?