用于分配用户角色的首选数据库设计方法? (帽子与团体)

时间:2009-01-08 20:14:34

标签: sql roles security-roles

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

有些人只是联系人 - 也就是说,他们的“人”表记录是我们需要存储的所有信息。许多其他人必须能够为各种系统承担不同的角色。其中,大部分都是以学生身份开始的。一些人从员工开始。作为学生的人可以成为实习生或表演者;员工可以成为学生;所有教师都是员工和表演者等。

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

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

我的问题是,实施模型有什么缺点?我能想到的唯一另一个选择是为人员表填充对于大多数条目将是空的和无用的字段,然后有一个人们可以属于的“组”的繁琐表,然后几乎每个表都有系统有一个人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;

9 个答案:

答案 0 :(得分:9)

去年我经历了类似的事情。那里的问题是:我们是明确地还是一般地模拟我们的实体?在你的例子中,这意味着拥有像老师,学生等一样的实体/表格,它们之间是否存在直接关系。

最后我们选择了通用的“派对”模式。党的模式如下:

  • 派对代表个人或组织;
  • 大多数派对类型都有一个依赖表来存储额外信息,具体取决于派对类型,例如人员,组织,公司;
  • 学生或教师之类的事情派对角色。一方可能有任意数量的派对角色。例如,一个人可以是教师和学生;
  • 类似于派对角色关系的处理方式。例如,教师和学生角色之间的关系表示阶级关系;
  • 派对角色关系可以有子类型以获取额外信息。模型中的师生关系是一个注册,可能有你正在谈论的额外属性;
  • 各方之间没有直接关系。只有党派角色相互关联;和
  • 对于常见的信息分组,我们创建了视图,如果它有帮助,因为SQL可能有点复杂,因为关系更间接(例如,教师和学生的Party实体之间有三个表)。

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

答案 1 :(得分:1)

您描述的群组和帽子模型可以互换,一个到另一个。没有真正担心数据丢失。具体来说,“主人组”表可以通过“帽子人”表的外部联接和各种“帽子细节”表来生成。

如果你使用的是“帽子”模型,你需要确保给定的“帽子桌子”准确地包含了帽子的独特特征。与团体模型相比,那里的宽恕要少得多。

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

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

会有很大的帮助。

在切线说明中,我发现有用的一件事就是使用与原始表中主键相同的名称来调用外键。那样你就可以

INNER JOIN original_table USING (primary_key) 

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

答案 2 :(得分:0)

教师是唯一具有工资率的“人”吗?您可能通过这种方式限制您的设计。您可能想要做的是拥有一个属性表,用于存储“人”的其他属性。这将允许将来的修改。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

是的,教师是唯一有薪酬率的人。该领域应该更准确地称为“classPayRate” - 这是教师员工的一个特例。非教师员工在工资单系统中将其总小时数作为单独的行项目提交。

答案 5 :(得分:0)

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

然而,在任何形状或形式中,我都不会在人员表中存储电子邮件,地址,电话。这些都应该是他们自己的独立表,因为人们有多个电子邮件地址(工作和家庭),多个电话号码(工作,家庭,小区,传真)和多个地址(工作,家庭1,家庭2,学校等)。我会把每个放在自己的表中并为其分配一个类型,这样你就可以确定哪种类型的地址,电话等。

对于地址,电子邮件,电话,您可能需要一个标记来标识哪个是用于首先联系的主要记录。我们收集了我们的通信,它是一个与触发器保持同步的布尔值,因为每个拥有记录的人必须只有一个通信,所以如果它改变了,旧的必须自动重置,以及新的进入,如果它是第一个记录,它是自动设置的,如果删除了对应的记录,如果有剩余记录,它将被分配给另一个记录。

答案 6 :(得分:0)

为了安全起见,我更喜欢使用访问控制列表(ACL)。使用ACL,您有Principals(用户或用户组),Resources(例如文件,记录或记录组)和Actions(例如read,update,delete)。

默认情况下,没有人拥有任何权限。要授予权限,请添加像Bob拥有对文件Abc的读访问权限的条目。

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

答案 7 :(得分:0)

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

答案 8 :(得分:0)

之前我使用过Party模型。我真的解决了大部分的缺点。