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

时间:2009-04-17 12:26:58

标签: postgresql

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

12 个答案:

答案 0 :(得分:567)

将使用/选择授予单个表

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

多个表/视图(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;

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

多个表/视图(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 SELECT,用于copy-n-paste love。当然,这只适用于已经创建的表。

答案 1 :(得分:35)

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

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

答案 2 :(得分: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;

然后登录所有相关的机器(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

答案 3 :(得分:16)

<强> Reference taken from this blog:

创建只读用户的脚本:

.click()

为此只读用户分配权限:

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

答案 4 :(得分:11)

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

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

答案 5 :(得分:8)

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

答案 6 :(得分:4)

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

GRANT pg_read_all_data TO xxx;

答案 7 :(得分:2)

如果您的数据库位于公共架构中,则很容易(假设您已经创建了<div mdl class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdl-cell mdl-cell--5-col mdl-cell--8-col-tablet mdl-cell--4-col-phone"> <label class="mdl-textfield__label" for="promoCode_{{inRibbon}}">Promo code</label> <input class="mdl-textfield__input" type="text" id="promoCode" name="promoCode_{{inRibbon}}" [ngModelOptions]="{standalone: true}" [(ngModel)]="itemAvailabilityRequest.promoCode"> </div>

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

答案 8 :(得分:1)

这样做的不直接方法是在数据库的每个表上授予select:

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

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

答案 9 :(得分:1)

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

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

答案 10 :(得分:0)

摘自回复despesz'链接时发布的链接。

Postgres 9.x似乎有能力做所要求的事情。请参阅Grant On Database Objects段落:

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

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

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

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

答案 11 :(得分:0)

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