MySQL:限制每个用户对记录子集的访问

Eri*_*vdW 5 mysql records limit

我们使用了几个大致如下所示的表:

| ID  | DepartmentId | Data |
| 1   | 1            | ...  |
| 2   | 1            | ...  |
| 3   | 2            | ...  |
| 4   | 3            | ...  |
| 5   | 2            | ...  |
Run Code Online (Sandbox Code Playgroud)

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

例如,一个

SELECT * FROM DataTable
Run Code Online (Sandbox Code Playgroud)

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

实现这一目标的最佳方法是什么?

Ray*_*Ray 6

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;
Run Code Online (Sandbox Code Playgroud)

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

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

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