【问题标题】:How to grant limited permissions to PostgreSQL tables?如何授予 PostgreSQL 表的有限权限?
【发布时间】:2015-05-29 18:20:37
【问题描述】:

我正在考虑从 MySQL 切换到 PostgreSQL,因为 MySQL 在共享主机环境中全文功能的限制(不能更改最小字长)。我没有 PostgreSQL 的管理经验,并且正在努力理解向用户/角色授予权限的意义。

我的应用有两个用户,一个用于构建,一个用于运行时。我希望运行时用户拥有这些权限:

SELECT, INSERT, UPDATE, DELETE

我因此登录到 PostgreSQL:

sudo -u postgres psql postgres

在查阅了手册和各种互联网资源后,我创建了这个演示,目的是对未来的所有表拥有有限的权限。来自一个全新的数据库:

CREATE USER job_frontend PASSWORD 'password';
DROP DATABASE IF EXISTS job_frontend;
CREATE DATABASE job_frontend ENCODING 'UTF8';
CREATE ROLE job_runtime;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO job_runtime;
GRANT job_runtime TO job_frontend;

我的策略,这可能是我出错的地方:创建一个用户,为角色设置授权,然后将角色授权分配给用户。我需要从数据库中删除一些默认权限吗?在 MySQL 中,用户默认是没有权限的,我大概就是这个心态卡住了。

然后我用PDO/PHP尝试各种操作(当然我修改prepare()来运行我想要的项目:

<?php

$dsn  = 'pgsql:dbname=job_frontend;host=localhost;user=job_frontend;password=password';
$db = new PDO($dsn);

// These should succeed
$sqlRead = "SELECT * FROM x";
$sqlWrite = "INSERT INTO x (id) VALUES (1)";

// This should fail but in fact succeeds
$sqlCreate = "CREATE TABLE x (id INTEGER)";

$stmt = $db->prepare($sqlRead);
if ($stmt === false)
{
    print_r($db->errorInfo());
}

$stmt->execute();
echo "Count: " . $stmt->rowCount() . "\n";

if ($rows = $stmt->fetchAll(PDO::FETCH_ASSOC))
{
    print_r($rows);
}

根据评论,CREATE TABLE 成功,但我不希望它成功。我错过了什么?

我相信共享的 PostgreSQL 环境将是 8.3,但未来可能会提供更高版本(我注意到这一点,因为我看到有各种授权选项直到 9.x 才可用)。我在本地运行 9.3 来测试东西,但现在想保持它与 8.3 兼容(直到更高版本上线)。

【问题讨论】:

    标签: php postgresql pdo


    【解决方案1】:

    默认情况下,任何人都可以在“公共”模式中执行所有操作。

    postgres=# CREATE ROLE tom LOGIN; -- user without rights
    CREATE ROLE
    postgres=# SET role tom ;
    SET
    postgres=> CREATE TABLE bubu(a int);
    CREATE TABLE
    

    您必须在默认情况下从公共架构上的 PUBLIC 中删除 CREATE。

    postgres=# REVOKE CREATE ON SCHEMA public FROM public;
    REVOKE
    postgres=# SET role tom;
    SET
    postgres=> CREATE TABLE foo(a int);
    ERROR:  permission denied for schema public
    LINE 1: CREATE TABLE foo(a int);
                         ^
    

    【讨论】:

    • 啊哈,谢谢。那么我最好在自己的架构中创建所有内容,以便可以添加显式权限,还是使用public 一个(然后按照您所说的撤销)是很常见的?
    • 取决于,你做什么。从我的角度来看,您描述的两种方式都是+/-相同的。您可以不公开地执行“公共”模式,或者您可以创建自己的模式并通过search_path 直接在那里搜索默认表。结果完全一样。一种是类似“Oracle”的方式,第二种是类似“MySQL”的方式——但两者之间的差异为零。
    • 好的,谢谢 - 我会试一试并报告!
    • 想一想:在共享主机环境中,public 模式是否对所有用户可见?如果是这样,那将指向我创建自己的,我猜?
    • 我预计其他用户将无法访问您的数据库 - 因此对公共架构的访问被有效禁用。但这不是 PostgreSQL 的默认值——尽管我期望它必须是共享主机的默认值。 PostgreSQL 的理念与 MySQL 略有不同——它不会试图保护数据库模式——但它可以很好地保护数据。当您从 PUBLIC 中删除 USAGE 时,您的“公共”架构对其他用户隐藏。
    猜你喜欢
    • 1970-01-01
    • 2020-08-31
    • 1970-01-01
    • 2014-05-06
    • 2017-07-06
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多