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

Eth*_*han 393 postgresql

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

GRANT SELECT ON mydb.* TO 'xxx'@'%' IDENTIFIED BY 'yyy';
Run Code Online (Sandbox Code Playgroud)

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

我试过了...

postgres=# CREATE ROLE xxx LOGIN PASSWORD 'yyy';
postgres=# GRANT SELECT ON DATABASE mydb TO xxx;
Run Code Online (Sandbox Code Playgroud)

但似乎您可以在数据库上授予的唯一内容是CREATE,CONNECT,TEMPORARY和TEMP.

ara*_*nid 602

将使用/选择授予单个表

如果仅将CONNECT授予数据库,则用户可以连接但没有其他权限.您必须单独为表和名称上的名称空间(模式)和SELECT授予USAGE,如下所示:

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;
Run Code Online (Sandbox Code Playgroud)

多个表/视图(PostgreSQL 9.0+)

在最新版本的PostgreSQL中,您可以使用单个命令为模式中的所有表/视图/等授予权限,而不必逐个键入它们:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;
Run Code Online (Sandbox Code Playgroud)

这仅影响已创建的表.更强大的是,您可以在将来自动为新对象分配默认角色:

ALTER DEFAULT PRIVILEGES IN SCHEMA public
   GRANT SELECT ON TABLES TO xxx;
Run Code Online (Sandbox Code Playgroud)

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

多个表/视图(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');
Run Code Online (Sandbox Code Playgroud)

这应该在公共的所有表,视图和序列上输出相关的GRANT命令到GRANT SELECT,用于复制粘贴爱.当然,这仅适用于已创建的表.

  • 请注意,为了防止此用户能够创建新表,我不得不"在SCHUBL public FROM PUBLIC上创建REVOKE;".没有它,"只读"用户无法修改现有表,但可以在模式中创建新表并从这些表中添加/删除数据. (24认同)
  • 你应该将关于PG9的编辑放在帖子的顶部. (22认同)
  • 对于像我这样的新手,我认为值得一提的是你应该使用`psql mydb`来启动控制台,否则大多数这些操作都不行.它个人花了我相当多的时间来自己解决这个问题.希望这有助于某人. (8认同)
  • 尼斯.我要补充的一件事是你可能还需要允许这个用户读取序列; 所以:GRANT选择SCHEMA public TO xxx中的所有序列; (5认同)
  • @ Ajedi32这应该是公认答案的一部分!谢谢 (3认同)

bor*_*yer 37

请注意,PostgreSQL 9.0(今天在beta测试中)将有一个简单的方法:

test=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO joeuser;
GRANT
Run Code Online (Sandbox Code Playgroud)

  • 这仅适用于架构中的现有表.如果写入用户稍后创建或替换表,则只读用户将无权访问它们 (8认同)
  • 我必须在特定的数据库中才能工作。PostgreSQL 9.5。 (3认同)

Anv*_*esh 23

从这篇博客中摘录:

创建只读用户的脚本:

CREATE ROLE Read_Only_User WITH LOGIN PASSWORD 'Test1234' 
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION VALID UNTIL 'infinity';
Run Code Online (Sandbox Code Playgroud)

为此只读用户分配权限:

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;
Run Code Online (Sandbox Code Playgroud)

  • 需要指出的是,从“GRANT USAGE...”开始的指令(如表上的 GRANT 权限)应该在所需的数据库中运行,否则权限将不起作用。为此,您可以使用 `\connect db_name;` 连接到数据库(它也可以在 sql 文件中使用)。 (16认同)
  • 这是一个很好的答案,但缺少以下几点:```SCHEMA public GRANT SELECT ON TABLES TABLE ON SELECT ON TABLES select to Read_Only_User;```这也将允许将来读取同一数据库中创建的所有表。 (3认同)
  • 允许只读用户访问序列是不寻常的。读取序列会对其进行更新,通常只有INSERT才需要它们。 (2认同)

Jay*_*lor 21

这是我发现添加只读用户的最佳方式(使用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;
Run Code Online (Sandbox Code Playgroud)

然后登录所有相关的机器(主机+读取从机/热备机等)并运行:

$ 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
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这种方法,但我还需要将DATABASE [thedatabase]的GRANT CONNECT连接到[用户或角色]; 并授予SCHEMA公共使用权[用户或角色]; (2认同)

Adr*_*eil 14

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

要使用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;
Run Code Online (Sandbox Code Playgroud)

如果您的只读用户没有列出表的权限(即\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;
Run Code Online (Sandbox Code Playgroud)


小智 9

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

user@server:~$ sudo su - postgres
Run Code Online (Sandbox Code Playgroud)

创建 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
Run Code Online (Sandbox Code Playgroud)

启动 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
Run Code Online (Sandbox Code Playgroud)

连接到目标数据库:

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".
Run Code Online (Sandbox Code Playgroud)

授予所有需要的权限:

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
Run Code Online (Sandbox Code Playgroud)

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

target_database=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
ALTER DEFAULT PRIVILEGES
Run Code Online (Sandbox Code Playgroud)


Jak*_*tka 8

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


jos*_*iti 5

如果您的数据库位于公共模式中,则很容易(这假设您已经创建了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
Run Code Online (Sandbox Code Playgroud)

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

db=> ALTER USER readonlyuser SET search_path=customschema, public;
ALTER ROLE
Run Code Online (Sandbox Code Playgroud)


Lau*_*lbe 5

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

GRANT pg_read_all_data TO xxx;
Run Code Online (Sandbox Code Playgroud)

  • 但是,据我所知,这授予对实例中所有数据库的只读访问权限,而不是对特定数据库的只读访问权限,对吧? (3认同)