【问题标题】:MySQL conditional user permissionsMySQL 条件用户权限
【发布时间】:2012-06-12 18:39:51
【问题描述】:

问题...是否可以添加 MySQL 权限以仅允许根据权限选择字段?

例子:

  1. 用户user1 只能从users 表中选择/插入/删除,其中instance 列等于1(1 通过PHP 传递)。
  2. 用户user2 只能从users 表中选择/插入/删除,其中instance 列等于2(1 通过PHP 传递)。

这是背景信息:

我正在使用用于多个站点的相同代码库创建一个应用程序。应用内的条件会加载不同的布局。多个站点使用相同的数据库,因为大多数信息可以在站点之间共享。在一个站点上注册的用户还必须在另一个站点上注册(这是我们想要的,因为这些站点是“仅限受邀者”)

我想做的是让用户表:id、电子邮件、密码、实例。实例列将具有站点的 ID。

在应用层上,每次我需要从该表中选择/插入/删除时,我都会将 instance = [site_id] 附加到查询中...例如:SELECT * FROM users WHERE email = '' AND instance = [site_id];

【问题讨论】:

  • 由于应用程序端负责将 instance = x 添加到查询中,因此 MySQL 只是一个额外的安全措施,以防查询意外没有 instance = x。
  • 只是测试你的代码,编码中没有“意外”之类的东西
  • 感谢您的所有回答和冗长的讨论。我会考虑解决方案并给予适当的奖励。 @pyrate 我同意没有意外代码。对于多个开发人员,从长远来看,有时很难跟踪这类事情。提出这个问题的另一个原因是向与我们打交道的公司保证,在站点之间访问用户信息存在技术安全边界/限制。再次感谢!

标签: php mysql cakephp permissions


【解决方案1】:

不,权限是每个表,数据库,服务器等,但不是针对行,但是有一个解决方案,您可以使用查看表并为用户设置权限,例如

mysql> CREATE VIEW test.v AS SELECT * FROM t where email = '' AND instance = [site_id];

只需创建 2 个视图表并授予这些用户访问权限

这里是Mysql documentation

【讨论】:

  • 每次添加新列/更改结构时,两种不同的视图都会让人头疼,不是吗?
  • @pyrate 如果您更改表结构,我认为这对任何应用程序都会很痛苦,但是如果您所做的更改不会影响您创建视图的方式,那么根本没有问题
  • 你说得对,创建视图而不查看选择特定列不应该受到影响。但是,当您选择视图中的特定列时(通常您会这样做) - 您需要更改两个视图(如果您有十几个网站使用一个代码库,则不仅仅是两个视图),而不仅仅是表格。跨度>
  • @pyrate 同意,因为视图将指向不存在的东西,但存储过程、函数、触发器等也会发生同样的情况。
  • 好点。仍然 - 我不认为不同的视图是这里的最佳选择:每次添加新站点时 - 您都需要创建仅具有 1 个不同变量的新视图。听起来不像是最佳编码实践。
【解决方案2】:

据我所知,这是不可能的,MySQL 不允许条件用户。

为两个网站使用一个用户,并根据您的“实例”修改您的所有查询。因此,每次您查询特定于站点的内容时,您都会添加 WHERE instance = $site_id

【讨论】:

    【解决方案3】:

    MySQL 不便于根据连接到数据库的 MySQL 用户使用权限来锁定某些行。

    如果您想以这种方式限制用户,最好不要让他们直接访问数据库,而是让他们通过另一层连接。

    使用视图不是一个好主意 - 每个用户都必须使用不同的查询(引用他们自己的个人视图)来完成相同的事情。如果您只是限制用户可以看到的(而不是行),那么视图将是一个很好的解决方案。

    可以使用存储过程来完成您正在寻找的事情:

    # This table already exists in your schema
    CREATE TABLE `user` (
      `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
      `email` VARCHAR(50) NOT NULL,
      `instance` INT(10) UNSIGNED NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=INNODB;
    
    INSERT INTO `user`(`id`,`email`,`instance`) 
        VALUES ( NULL,'wat@lol.com','1');
    INSERT INTO `user`(`id`,`email`,`instance`) 
        VALUES ( NULL,'huh@bwu.com','2');
    INSERT INTO `user`(`id`,`email`,`instance`) 
        VALUES ( NULL,'no@yes.lol','1');
    
    # This would be a new table you would have to create
    CREATE TABLE `user_instance` (
      `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
      `user` VARCHAR(20) NOT NULL,
      `instance` INT(10) UNSIGNED NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `user_instance` (`user`,`instance`)
    ) ENGINE=INNODB;
    
    INSERT INTO `user_instance`(`user`,`instance`) VALUES ('user1','1');
    INSERT INTO `user_instance`(`user`,`instance`) VALUES ('user2','2');
    
    # This is a stored procedure that might accomplish what you want
    DELIMITER $$
    
    CREATE PROCEDURE `p_get_users`()
    BEGIN
        SELECT `user`.`id`, `user`.`email`
        FROM `user`
        WHERE `user`.`instance` IN(
            SELECT `instance` 
            FROM `user_instance` 
            WHERE `user` = USER());
    END$$
    
    DELIMITER ;
    

    【讨论】:

      猜你喜欢
      • 2011-01-16
      • 1970-01-01
      • 2011-05-06
      • 2012-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 2020-10-08
      相关资源
      最近更新 更多