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


419

我想在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。

Answers:


641

将使用情况/选择授予单个表

如果仅将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;

这只会影响已经创建的表。功能更强大的是,将来您可以自动将默认角色分配给新对象

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

请注意,默认情况下,这仅会影响发出此命令的用户创建的对象(表):尽管也可以在发出用户所属的任何角色上进行设置。但是,在创建新对象时,您不会为您所隶属的所有角色选择默认特权...因此仍然存在一些麻烦。如果采用数据库具有所有者角色的方式,并且以该所有者角色的身份进行模式更改,则应为该所有者角色分配默认特权。恕我直言,这有点令人困惑,您可能需要进行试验以提出功能正常的工作流程。

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

为了避免冗长的多表更改中的错误,建议使用以下“自动”过程来生成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命令公开输出到所有表,视图和序列上,以实现复制n粘贴。自然,这将仅应用于已经创建的表。


22
您应该将有关PG9的编辑内容放在帖子的顶部。
Danilo Bargen

5
真好 我要补充的一件事是,您可能还需要允许该用户读取序列。所以:在SCHEMA public TO xxx上对所有序列进行GRANT SELECT;
JJC

26
请注意,为防止该用户能够创建新表,我不得不这样做REVOKE CREATE ON SCHEMA public FROM PUBLIC;。否则,“只读”用户将无法修改现有表,但可以在架构中创建新表并从这些表中添加/删除数据。
Ajedi32

3
@ Ajedi32这应该是已接受答案的一部分!谢谢
Asfand Qazi

12
对于像我这样的新手,我认为值得一提的是您应该使用psql mydb大多数其他操作无法启动的控制台。我个人花了很多时间自行解决。希望这对某人有帮助。
Anass

41

请注意,PostgreSQL 9.0(今天处于beta测试中)将有一种简单的方法

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

3
我必须在特定的数据库中才能正常工作。PostgreSQL 9.5。
user1158559 '16

8
这仅适用于架构中的现有表。如果写用户以后创建或替换表,则只读用户将无权访问它们
Annb

32

从此博客引用:

创建只读用户的脚本:

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;

6
这是一个很好的答案,但缺少以下几点: ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User; 将来还可以读取在同一数据库中创建的所有表。
拉夫贝克(Ravbaker)

2
允许只读用户访问序列是不寻常的。读取序列会对其进行更新,并且通常只需要INSERTs即可。
jpmc26

为了完整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
法比恩·哈达迪

@FabienHaddadi这意味着除非您有一些不同寻常的要求,否则我认为不需要将序列的任何权限授予只读用户。
jpmc26

24

这是我发现添加只读用户(使用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;

然后登录到所有相关机器(主控+读从属/热备用等),然后运行:

$ 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

2
我喜欢这种方法,但我还需要将DATABASE [数据库]上的连接授予[用户或角色];在[用户或角色]上向SCHEMA公开授予使用权;
伊恩·康纳

1
公共模式仍然允许此类用户创建表。此外,新表也没有涉及,序列也没有。不幸的是,这一切都比这复杂得多。:-/一旦验证了更多信息,我将发布最终的操作。
JJC 2014年

在上面的脚本中,您尝试两次创建角色。我怀疑您打算在启用登录角色并设置密码时使用“ ALTER ROLE ...”
Bogdan 2015年

如果您已经有用户,则在创建只读角色并授予select perms后,将新角色授予该用户:GRANT readonly TO <USER>
gonz

18

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

要使用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;


4

我会仔细阅读所有可能的解决方案,如果您在授予权限之前记得连接到数据库,那一切都很好;)无论如何,感谢所有其他解决方案!!!

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

更改目标数据库公共shema的默认特权:

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

3

如果您的数据库位于公共架构中,则很简单(假设您已经创建了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

1

做到这一点的不简单方法是在数据库的每个表上授予选择权:

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

您可以通过从数据库元数据生成授权语句来实现自动化。


1
CREATE USER username SUPERUSER  password 'userpass';
ALTER USER username set default_transaction_read_only = on;

0

摘自为回应despesz的链接而发布的链接。

Postgres 9.x似乎可以执行请求的功能。请参阅以下内容的“授予数据库对象”段落:

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

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

此页面还讨论了角色的使用和称为“所有特权”的特权。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.