【问题标题】:Allow MySQL users access to select on all views, but not tables允许 MySQL 用户访问选择所有视图,但不允许选择表
【发布时间】:2016-02-27 15:02:35
【问题描述】:

我如何允许用户仅选择访问视图而不是任何基础表?

我知道如何使用

一次授予一个权限

grant select on database.viewName to 'User'

但我试图让用户或配置文件有权访问所有视图,而无需在创建新视图时逐一运行授权。

在 Sequel Pro 中,在用户>全局权限和架构权限下,我添加了“显示视图”,但这不起作用。

【问题讨论】:

  • 也许我措辞不好。我了解运行 grant select on database.viewName to 'User' 将授予对一个视图的访问权限。我想要一个用户配置文件设置,用户可以自动访问以从所有视图中提取内容,但不能从基础表中提取内容。创建新视图后,用户无需运行另一批授权脚本即可访问。有了新表,他们仍然无法访问。

标签: mysql view permissions


【解决方案1】:

我不相信这是可能的。

Mysql GRANT 命令采用GRANT permission ON object_type 的形式

当以下对象是表、存储函数或存储过程时,应将 object_type 子句(如果存在)指定为 TABLE、FUNCTION 或 PROCEDURE。

https://dev.mysql.com/doc/refman/5.7/en/grant.html

我认为没有任何工具可以仅授予视图权限。

请记住,在 mysql 中,视图只是一个查询,每当您从中选择时就会执行该查询。它没有自己的数据存储或索引。因此,我希望您必须有权访问基础表才能使视图可用。

【讨论】:

  • 这个答案不正确!正如链接文档所说:Table-level privileges apply to base tables and views. 正确的解决方案是以定义者的名义创建要运行的视图,定义者必须具有对基础表的选择访问权限。
【解决方案2】:

我会展示它,可能需要进行一些编辑才能完成。因为我必须在底部附加控制台输出。

架构

create table users
(   userId int auto_increment primary key,
    userName varchar(100) not null
    -- etc
);
insert users(userName) values ('Joe'),('Gertrude');

-- drop table secretdata;
create table SecretData
(   id int auto_increment primary key,
    userId int not null,
    theKey varchar(100) not null,
    theValue varchar(1000) not null,
    key(userId),
    CONSTRAINT fk_sd_users FOREIGN KEY (userId) REFERENCES users(userId)
);
insert secretdata(userId,theKey,theValue) values 
(1,'FB Password','8*&Fjj_anchovieS'),
(1,'Proper response','I love the meal, just like I like it'),
(2,'thing7','goat');

视图

CREATE VIEW userSecrets AS 
    select u.userId,u.userName,s.theKey,s.theValue
    from users u
    join SecretData s
    on s.userId=u.userId;

select * from userSecrets where userId=2; -- 目前在这里工作

注意我的数据库名称是so_gibberish

以下是您要求授予查看权限的内容:

GRANT SELECT ON so_gibberish.userSecrets TO 'john'@'host';

↑ ↑ 如此配置的用户然后可以针对视图进行查询。 ↑ ↑

然而,

CREATE USER 'plebian2'@'localhost' IDENTIFIED BY 'mypass';
GRANT SELECT ON so_gibberish.userSecrets TO 'plebian2'@'localhost';

该用户确实有权使用视图,但没有直接访问基础表。

控制台输出:

OS Prompt>mysql -u plebian2 -p
Enter password: ******

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 938
Server version: 5.6.24-log MySQL Community Server (GPL)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| so_gibberish       |
+--------------------+
2 rows in set (0.00 sec)

mysql> use so_gibberish;
Database changed

mysql> show tables;
+------------------------+
| Tables_in_so_gibberish |
+------------------------+
| usersecrets            |
+------------------------+
1 row in set (0.00 sec)

mysql> select * from users;
ERROR 1142 (42000): SELECT command denied to user 'plebian2'@'localhost' for table 'users'

mysql> select * from usersecrets;
+--------+----------+-----------------+--------------------------------------+
| userId | userName | theKey          | theValue                             |
+--------+----------+-----------------+--------------------------------------+
|      1 | Joe      | FB Password     | 8*&Fjj_anchovieS                     |
|      1 | Joe      | Proper response | I love the meal, just like I like it |
|      2 | Gertrude | thing7          | goat                                 |
+--------+----------+-----------------+--------------------------------------+
3 rows in set (0.00 sec)

最后,我希望看到标题为Access Control for Stored Programs and Views 的手册页,了解Definer 权限如何影响最终状态的有效权限。特别是,当定义者拥有比使用视图的用户帐户更少的权限时(这是一个相当奇怪的情况,但确实存在)。

角色

回应您在“答案”下的评论。

我基本上对 mysql 中缺少来自微软世界的嵌入角色感到不满。这意味着,有组成的角色,用户附加到角色,并且在角色级别(在 MSFT 世界中)执行授权。在那里,在 MSSQL 中,在每个创建任何块(存储过程等)的底部,将是我在角色级别进行授权的块。

所以进入 mysql,我必须创建该角色到用户映射。好消息,我只需要做一次。在我运行的块的末尾(如果存在删除/创建),它会调用直接操纵INFORMATION_SCHEMA.user_privileges 等。但在非常高的水平上,就像 MSFT 一样,最终结果就是我想要的。即授予的权限。

那是一整罐蠕虫。但没有它,祝你好运。

grant 等命令和其他一些命令可以在后台自行执行。他们几乎没有什么神圣之处。然而,它们的存在是为了保护新手程序员。而那些放弃那些警告标志说要小心的人往往会思考,

“我如何取回我的数据。我知道它在某个地方。也许我 我不应该在幕后做我刚刚做的事情”

但绝对是需要修补的东西,尤其是在一次性数据库中(你不关心的)。更好的是,在您不关心的 mysql 实例上执行此操作。因为我们在比数据库级别更高的级别讨论系统范围的影响。

【讨论】:

  • 感谢您的帮助,但这仍然需要在添加每个视图时为每个用户运行授权。这是我一直在使用的,不足以作为长期解决方案。再次感谢!
【解决方案3】:

此答案已使用 MySQL 8.0.23 验证。

  1. 确保您的视图设置为使用DEFINER 的凭据运行,这样调用用户不需要任何TABLE 权限;不这样做会导致错误。有关{DEFINER|INVOKER} 参数see here 的更多详细信息。

  2. 创建您的用户,完全不分配任何权限。

  3. 作为root或其他具有足够权限的用户,执行以下命令:

    GRANT SELECT ON <database>.<view_name> TO '<user>'@'<host>';
    

因此,如果我的数据库是 cars 并且视图名为 service_history,并且我有一个用户 john.doe 需要从任何主机访问它,我将执行以下操作:

GRANT SELECT ON cars.service_history TO 'john.doe'@'%';

注意'%' 是如何用于指示任何主机都可以接受的,您可以将其替换为 IP 地址,也可以是主机名(但我没有测试过)。

【讨论】:

    【解决方案4】:

    我通过使用 user() 作为表上的过滤器并设置 SQL SECURITY DEFINER,对视图和源表使用单独的架构来实现这一点。

    示例代码

    CREATE 
        ALGORITHM = UNDEFINED 
        DEFINER = `xxxxxx`@`%` 
        SQL SECURITY DEFINER
    VIEW `XX`.`assets` AS
        SELECT 
            `a`.`ID` AS `ID`,
            `a`.`serial_no` AS `serial_no`,
            `a`.`sys_id` AS `sys_id`,
            `a`.`status` AS `status`,
            `a`.`unit_name` AS `unit_name`,
            `a`.`ip` AS `ip`,
            `a`.`tzOffset` AS `tzOffset`
        FROM
            ((`YY`.`Cust_Link_Table` `l`
            JOIN `YY`.`systems` `s` ON ((`l`.`cust_id` = `s`.`cust_id`)))
            JOIN `YY`.`assets` `a` ON ((`s`.`sys_id` = `a`.`sys_id`)))
        WHERE
            (`l`.`db_user` = CONVERT( LEFT(USER(), (LOCATE('@', USER()) - 1)) USING UTF8MB4))
    

    【讨论】:

      猜你喜欢
      • 2012-12-18
      • 2015-02-08
      • 2011-07-26
      • 2019-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-30
      • 1970-01-01
      相关资源
      最近更新 更多