为什么这些命令不能在PostgreSQL中创建只读用户?

时间:2015-11-18 17:18:59

标签: postgresql

我已仔细审核过本网站上的类似问题,但无法让它发挥作用。

  • 我在Ubuntu 14.04(Vagrant box)上使用PostgreSQL 9.3.9(从软件包安装)。
  • 我正在创建一个名为site的新数据库,由postgres拥有。
  • 我想创建一个名为readonly的只读用户,可以访问此数据库。
  • 我试图将它们锁定在SCHEMA public之外,但无论我尝试做什么,他们仍然可以创建表格。

任何人都可以帮助我理解为什么这个用户仍然可以写入数据库,尽管完全被锁定了?这是我采取的步骤;首先,设置实体并明确锁定所有权限:

postgres=# CREATE DATABASE site;
CREATE DATABASE
postgres=# CREATE ROLE readonly UNENCRYPTED PASSWORD 'password' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1;
CREATE ROLE
postgres=# REVOKE ALL ON SCHEMA public FROM public;
REVOKE
postgres=# REVOKE ALL ON SCHEMA public FROM readonly;
REVOKE
postgres=# REVOKE ALL ON DATABASE site FROM public;
REVOKE

让我们检查readonly无法连接:

vagrant@vagrant-web1:~$ PGHOST=127.0.0.1 PGPASSWORD=password psql -U readonly site
psql: FATAL:  permission denied for database "site"
DETAIL:  User does not have CONNECT privilege.

到目前为止,一切都是正确的。现在超级用户授予一个权限:

postgres=# GRANT CONNECT ON DATABASE site TO readonly;
GRANT

这是系统崩溃的地方。 readonly用户可以登录并创建表格:

vagrant@vagrant-web1:~$ PGHOST=127.0.0.1 PGPASSWORD=password psql -U readonly site
psql (9.3.9)
SSL connection (cipher: DHE-RSA-AES256-GCM-SHA384, bits: 256)
Type "help" for help.

site=> CREATE TABLE orders(id int);
CREATE TABLE
site=> \dt
         List of relations
 Schema |  Name  | Type  |  Owner
--------+--------+-------+----------
 public | orders | table | readonly
(1 row)

这让我陷入了几个小时。任何帮助将不胜感激。

额外信息:数据库中只有一个架构。以下是\du的输出结果:

postgres=# \du
                                                    List of roles
      Role name      |                   Attributes                   |                   Member of
---------------------+------------------------------------------------+-----------------------------------------------
 postgres            | Superuser, Create role, Create DB, Replication | {}
 readonly            |                                                | {}

这里是\ list:

的输出
postgres=# \list
                                                     List of databases
      Name       |        Owner        | Encoding |   Collate   |    Ctype    |              Access privileges
-----------------+---------------------+----------+-------------+-------------+---------------------------------------------
 postgres        | postgres            | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 site            | postgres            | UTF8     | en_US.UTF-8 | en_US.UTF-8 | postgres=CTc/postgres                      +
                 |                     |          |             |             | readonly=c/postgres
 template0       | postgres            | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres                                +
                 |                     |          |             |             | postgres=CTc/postgres
 template1       | postgres            | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres                                +
                 |                     |          |             |             | postgres=CTc/postgres

1 个答案:

答案 0 :(得分:1)

您在数据库REVOKE ALL ON SCHEMA public ...中发出了命令postgres,而不是site。检查一下:

site=> \dn+
                          List of schemas
  Name  |  Owner   |  Access privileges   |      Description       
--------+----------+----------------------+------------------------
 public | postgres | postgres=UC/postgres+| standard public schema
        |          | =UC/postgres         | 
(1 row)

=UC/postgres表示public具有架构public的使用权和创建权限。

请执行以下操作:

site=> \c site postgres
You are now connected to database "site" as user "postgres".
site=# REVOKE ALL ON SCHEMA public FROM public;
REVOKE

现在它起作用了:

site=# \c site readonly
You are now connected to database "site" as user "readonly".
site=> create table t(n numeric);
ERROR:  no schema has been selected to create in
site=> create table public.t(n numeric);
ERROR:  permission denied for schema public