【问题标题】:Preferred database design method for assigning user roles? (Hats vs. Groups)分配用户角色的首选数据库设计方法? (帽子与组)
【发布时间】:2010-09-30 08:32:14
【问题描述】:

我有一个中等大小的 MySQL 数据库,其中包含一个主要的“persons”表,其中包含连接到剧院和剧院学校的每个人的基本联系信息,我负责维护和开发许多 Web 应用程序。

有些人只是联系人——也就是说,他们的“persons”表记录是我们需要存储的关于他们的所有信息。许多其他人虽然必须能够为各种系统承担不同的角色。其中,大多数都是从学生开始的。有些人从员工开始。学生可以成为实习生或表演者;员工可以成为学生;所有的老师都是雇员和表演者等等。

本质上,它们是各种不同的“帽子”,任何个人都可能必须戴上这些“帽子”才能访问系统的不同部分并与之交互,以及在我们的公共页面上提供有关它们的信息网站。

我对实现这个模型的选择是有几个其他的表来代表这些“帽子”——这些表包含补充基本“人”信息的元信息,所有这些都使用“人”ID作为他们的主键.例如,作为教师的人在教师表中有一条记录,其中包含他或她的简短传记信息和工资率。所有教师也是员工(但并非所有员工都是教师),这意味着他们在员工表中有一条记录,允许他们将工作时间提交到我们的工资系统中。

我的问题是,这样实现模型有什么缺点?我能想到的唯一另一个选择是用对于大多数条目来说是空的和无用的字段来填充persons表,然后有一个人可以属于的繁琐的“组”表,然后几乎每个表都有每个系统有一个人person_id外键,然后依靠业务逻辑来验证所引用的person_id是否属于适当的组;但这很愚蠢,不是吗?

下面是一些示例表声明,希望它们可以展示我目前如何将所有这些放在一起,并希望说明为什么我认为这是一种更明智的方式来模拟系统必须处理的各种情况的现实与。

欢迎提出任何建议和建议。感谢您的宝贵时间。

编辑 一些受访者提到使用 ACL 来确保安全 - 我在最初的问题中没有提到我实际上是在使用单独的 ACL 包来对不同的系统。我的问题更多是关于在数据库模式中存储有关人员的元数据的最佳实践。

CREATE TABLE persons (
    `id`            int(11) NOT NULL auto_increment,
    `firstName`     varchar(50) NOT NULL,
    `middleName`    varchar(50) NOT NULL default '',
    `lastName`      varchar(75) NOT NULL,
    `email`         varchar(100) NOT NULL default '',
    `address`       varchar(255) NOT NULL default '',
    `address2`      varchar(255) NOT NULL default '',
    `city`          varchar(75) NOT NULL default '',
    `state`         varchar(75) NOT NULL default '',
    `zip`           varchar(10) NOT NULL default '',
    `country`       varchar(75) NOT NULL default '',
    `phone`         varchar(30) NOT NULL default '',
    `phone2`        varchar(30) NOT NULL default '',
    `notes`         text NOT NULL default '',
    `birthdate`     date NOT NULL default '0000-00-00',
    `created`       datetime NOT NULL default '0000-00-00 00:00',
    `updated`       timestamp NOT NULL,
    PRIMARY KEY (`id`),
    KEY `lastName` (`lastName`),
    KEY `email` (`email`)
) ENGINE=InnoDB;

CREATE TABLE teachers (
    `person_id`     int(11) NOT NULL,
    `bio`           text NOT NULL default '',
    `image`         varchar(150) NOT NULL default '',
    `payRate`       float(5,2) NOT NULL,
    `active`        boolean NOT NULL default 0,
    PRIMARY KEY (`person_id`),
    FOREIGN KEY(`person_id`) REFERENCES `persons` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;

CREATE TABLE classes (
    `id`            int(11) NOT NULL auto_increment,
    `teacher_id`    int(11) default NULL,
    `classstatus_id` int(11) NOT NULL default 0,
    `description`   text NOT NULL default '',
    `capacity`      tinyint NOT NULL,
    PRIMARY KEY(`id`),
    FOREIGN KEY(`teacher_id`) REFERENCES `teachers` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    FOREIGN KEY(`classstatus_id`) REFERENCES `classstatuses` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    KEY (`teacher_id`,`level_id`),
    KEY (`teacher_id`,`classstatus_id`)
) ENGINE=InnoDB;

CREATE TABLE students (
    `person_id`     int(11) NOT NULL,
    `image`         varchar(150) NOT NULL default '',
    `note`          varchar(255) NOT NULL default '',
    PRIMARY KEY (`person_id`),
    FOREIGN KEY(`person_id`) REFERENCES `persons` (`id`)
    ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;

CREATE TABLE enrollment (
    `id`                int(11) NOT NULL auto_increment,
    `class_id`          int(11) NOT NULL,
    `student_id`        int(11) NOT NULL,
    `enrollmenttype_id` int(11) NOT NULL,
    `created`           datetime NOT NULL default '0000-00-00 00:00',
    `modified`          timestamp NOT NULL,
    PRIMARY KEY(`id`),
    FOREIGN KEY(`class_id`) REFERENCES `classes` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    FOREIGN KEY(`student_id`) REFERENCES `students` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE,
    FOREIGN KEY(`enrollmenttype_id`) REFERENCES `enrollmenttypes` (`id`)
        ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;

【问题讨论】:

    标签: sql roles security-roles


    【解决方案1】:

    去年我也经历过类似的事情。问题是:我们是显式地还是一般地建模我们的实体?在您的示例中,这意味着实体/表(例如教师、学生等)之间是否存在直接关系。

    最后我们选择了一个通用的“Party”模型。党模型如下:

    • 政党代表个人或组织;
    • 大多数Party 类型都有一个依赖表来存储额外信息,具体取决于Party 类型,例如Person、Organization、Company;
    • 诸如学生或教师之类的东西是派对角色。一方可以有任意数量的方角色。例如,一个人可能既是教师又是学生;
    • 诸如类之类的事情作为党的角色关系来处理。例如,教师和学生角色之间的关系表示类关系;
    • 当事方角色关系可以具有用于额外信息的子类型。您的模型中的师生关系是一种注册,它可能具有您所说的额外属性;
    • 各方之间没有直接关系。只有当事方角色相互关联;和
    • 对于常见的信息分组,如果有帮助,我们会创建视图,因为 SQL 可能有点复杂,因为关系更加间接(例如,教师和学生的党实体之间存在三个表)。

    这是一个非常强大的模型,在 CRM 类型系统中非常常见。这个模型几乎来自"The Data Model Resource Book: Volume 1",这是一个很好的资源。

    【讨论】:

    • 你把我的问题比我做得更好,谢谢!这是一个非常有趣的想法,感谢您的总结和书籍推荐。如果我可以投票,我会的!
    【解决方案2】:

    您描述的组和帽子模型是可转换的,一个到另一个。无需担心数据丢失。具体来说,“master groups”表可以通过“hat person”表与各种“hat detail”表的外部连接来生成。

    如果您使用的是“帽子”模型,则需要确保给定的“帽子表”准确地封装了该帽子的独特特征。与团体模型相比,那里的宽恕要少得多。

    如果您采用这种方式,您可能需要为常见任务设置一些视图 - 例如,如果有人在“教师姓名”字段中输入内容,并且您想弹出一些自动完成功能,则有一个视图基本上是

    SELECT firstName, lastName 
    FROM persons 
    INNER JOIN teachers ON persons.id = teachers.person_id 
    

    会有很大帮助。

    顺便说一句,我发现有用的一件事是使用与原始表中的主键相同的名称来调用外键。这样你就可以了

    INNER JOIN original_table USING (primary_key) 
    

    在您的 FROM 中,而不是使用 WHERE 或 ON 等效项。

    【讨论】:

      【解决方案3】:

      教师是唯一有工资的“人”吗?这样做可能会限制您的设计。您可能想要做的是有一个属性表来存储“人”的附加属性。这将允许将来进行修改。

      【讨论】:

        【解决方案4】:

        我喜欢帽子方法。过去,我实现了帽子和组的组合。基本上,有一个用户可以执行的所有可能操作(权限)的列表。然后我有一个组表。每个组可以有 1 个或多个操作(权限)。然后我将用户分配到组。

        这为我提供了很大的灵活性。我可以在我的许可中获得非常好的颗粒。我也可以通过编辑组来快速更改许多人的权限。事实上,我有权限页面设置来使用相同的权限。这允许最终用户(不是我)为其他用户设置权限。

        【讨论】:

        • 感谢您的回复 - 我正在使用单独的 ACL 包来获得细粒度的权限,以确定用户在网站上可以做什么或不可以做什么,所以我 100% 同意您的意见关于组合方法。
        【解决方案5】:

        是的,教师是唯一有这样的工资率的人。该字段应该更准确地称为“classPayRate”——这是教师雇员的特例。非教师员工在我们的工资系统中将他们的总小时数作为单独的项目提交。

        【讨论】:

          【解决方案6】:

          我可能会将教师更改为员工并添加员工类型。

          但是,我绝不会在人员表中存储电子邮件、地址、电话。这些都应该是他们自己的单独表格,因为人们有多个电子邮件地址(工作和家庭)、多个电话号码(工作、家庭、手机、传真)和多个地址(工作、家庭 1、家庭 2、学校等)。我会将每个都放在自己的表中并为其分配一个类型,以便您可以识别哪个类型的地址、电话等。

          对于地址、电子邮件、电话,您可能需要一个标志来识别哪个是用于首先联系的主要记录。我们调用我们的对应关系,它是一个布尔值,通过触发器保持最新,因为每个有记录的人必须有一个且只有一个对应关系,所以如果它发生变化,旧的必须自动重置以及新的进入,如果是第一条记录自动设置,如果对应的记录被删除,如果有剩余记录,它会分配给另一个。

          【讨论】:

            【解决方案7】:

            为了安全,我更喜欢使用访问控制列表 (ACL)。使用 ACL,您可以拥有 Principal(用户或用户组)、Resources(例如文件、记录或记录组)和 Actions(例如读取、更新、删除)。

            默认情况下,没有人有任何特权。要授予权限,您可以添加一个条目,例如 Bob 对文件 Abc 具有读取权限。

            您应该能够找到可以帮助您实现此类功能的代码。在 Java 中,JAAS 支持这种方法。

            【讨论】:

              【解决方案8】:

              我正在使用 ACL 包来获得网站上的细粒度权限 - 我的问题的核心更多是关于如何为具有不同角色的个人存储元数据,并在系统中构建一些数据完整性保护措施(这样一个人必须有一个教师记录才能被设置为班级的教师 - 外键约束引用教师表,而不是人员表)。

              【讨论】:

                【解决方案9】:

                我以前用过派对模式。我确实解决了大部分的缺点。

                【讨论】:

                  猜你喜欢
                  • 2015-02-21
                  • 2014-11-26
                  • 2016-03-30
                  • 2012-03-08
                  • 2017-05-24
                  • 1970-01-01
                  • 2021-12-23
                  • 2017-10-06
                  • 1970-01-01
                  相关资源
                  最近更新 更多