【问题标题】:MySQL: Limit access to subset of records for each userMySQL:限制每个用户对记录子集的访问
【发布时间】:2014-03-21 11:55:24
【问题描述】:

我们正在使用几个大致如下所示的表格:

| ID  | DepartmentId | Data |
| 1   | 1            | ...  |
| 2   | 1            | ...  |
| 3   | 2            | ...  |
| 4   | 3            | ...  |
| 5   | 2            | ...  |

我们有大约 200 个 MySQL 用户,每个用户都与一个或多个部门相关联(通过一个简单的 Username/DepartmentId 表) 我们希望将访问(SELECT、UPDATE)限制为每个用户的正确记录子集。

例如,一个

SELECT * FROM DataTable

与部门 1 和 3 关联的用户“Bob”应返回记录 1、2 和 4。 与部门 1 关联的用户“Alice”的相同查询应该只返回记录 1 和 2。

最好的方法是什么?

【问题讨论】:

  • 您必须从应用程序端执行此操作。实际上,这很容易。
  • 当您说 Mysql 用户时,您指的是 mysql.user 表中列出的 MySQL 用户,您连接到 DB跨度>
  • 我的意思是实际的 MySQL 用户。我们让 MySQL 尽可能多地处理用户权限。这样,用户只有在实际连接和访问数据库时才能登录我们的应用程序。
  • @ErikvdW 看到您希望他们能够使用 sequel pro 或 phpmyadmin 等管理工具直接登录并使用表格。另外,我将修改我的答案以显示如何添加您需要的部门映射表,因为它不是行到用户,而是行到部门。逻辑还是基本一样的。

标签: mysql limit records


【解决方案1】:

MySQL 没有基于行的权限。您可以做的最好的事情是构建视图以显示某些记录。一种简单的方法是将带有 mysql 用户名的映射表添加到他们有权访问的部门 id 中,并将该映射表上的视图选择连接到原始的,仅限于当前的请求用户。可以使用CURRENT_USER()获取当前mysql用户。

然后将用户限制在视图中,而不是原始表中。

以下是步骤的细分:

   CREATE TABLE `mysqluser_dept` (
     `mysqluser` varchar(255) NOT NULL DEFAULT '',
     `DepartmentId` int(11) NOT NULL DEFAULT '0',
       PRIMARY KEY (`mysqluser`,`DepartmentId`)
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    CREATE SQL SECURITY INVOKER VIEW filtered_view AS 
           SELECT o.* FROM original_table o 
               JOIN mysqluser_dept m on m.DepartmentId = o.DepartmentId
                    WHERE m.mysqluser = current_user() GROUP by o.id;

如果您不想显示原始表的所有列,可以根据需要将视图中的select o.* 限制为一组特定的字段。现在根据需要填充mysqlusers 到departmet 列的映射表。当前用户返回确切的用户,因此使用完整的用户字符串(用户名@localhost、用户名@% 等)或更改视图以在比较中截断主机。

现在用户可以访问filtered_view,并且只能看到他们有权访问的行(按部门)。奖励:由于这是多对多,如果需要,您可以在多个部门中拥有人员 - 原始表主键上的分组避免重复记录。

您可能还想锁定映射表 mysqluser_department 的权限。

【讨论】:

  • 虽然这不是解决方案(不想直接将每条记录限制为特定用户,而是通过部门键),但它确实对我有很大帮助。我没有想过使用 current_user() 来使用视图。我曾考虑为每个用户创建临时登录视图,但这要简单得多。谢谢!
  • +1。另外,我意识到这篇文章是 5 年前的,但我有一个问题:除非我遗漏了什么,否则使用 INVOKER 安全选项似乎需要受限用户对基础表具有选择权限。选择INVOKER有什么理由吗?使用 DEFINER 安全性和 USER() 函数不是更好吗?
  • @favq,我只是在尝试了 Ray 使用 DEFINER 安全性而不是 INVOKER 的方法几个小时后才阅读您的评论。然后我突然发现我错过了什么:在 where 语句中,我没有将 Current_user() 更改为 User()。我总是得到空白结果,因为 where 语句总是返回 false 哈哈哈。感谢您的精彩观点。
猜你喜欢
  • 2013-11-13
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多