多种权限类型(角色)以单小数形式存储在数据库中
我在这里要问一个问题,关于我的某些用户/角色数据库表的设计是否可以接受,但是经过一些研究,我遇到了这个问题:
处理多种权限类型的最佳方法是什么?
这听起来像是一种创新的方法,所以我将多个权限定义为单个小数(我假定为int数据类型),而不是多对多的users_to_roles表。这意味着单个用户的所有权限都在一行中。除非我们阅读其他问题和答案,否则可能没有任何意义。
我无法理解这一点。有人可以解释转换过程吗?听起来"正确",但我只是不了解如何将角色转换为小数,然后再将其放入数据库,以及如何将其从数据库中转换回去。我正在使用Java,但是如果我们不使用它,那也将很酷。
这是其他问题被删除时的原始答案:
"就我个人而言,有时我使用标记的权限枚举。通过这种方式,我们可以对枚举项使用AND,OR,NOT和XOR按位运算。
[Flags] public enum Permission { VIEWUSERS = 1, // 2^0 // 0000 0001 EDITUSERS = 2, // 2^1 // 0000 0010 VIEWPRODUCTS = 4, // 2^2 // 0000 0100 EDITPRODUCTS = 8, // 2^3 // 0000 1000 VIEWCLIENTS = 16, // 2^4 // 0001 0000 EDITCLIENTS = 32, // 2^5 // 0010 0000 DELETECLIENTS = 64, // 2^6 // 0100 0000 }
然后,我们可以使用AND按位运算符组合多个权限。
例如,如果用户可以查看和编辑用户,则该操作的二进制结果为0000 0011,转换为十进制为3.
然后,我们可以将一个用户的权限存储到数据库的单个列中(在我们的示例中为3)。
在应用程序内部,我们只需要执行另一个按位操作(OR)即可验证用户是否具有特定的权限。"
解决方案
回答
实际上,这就是我们在作为DBA的相当大的Web应用程序中确定权限的方式。
如果我们打算做这样的事情,那么拥有数字表将使我们真正受益。它将使计算速度更快。
基本设置包括下表:
- 组-适用于许多用户和许多安全点
- 安全点-包含一个用于匿名授权的值和一个用于不属于单独组的已认证用户的值
- 组安全点联接表
- 一个特殊的BitMask数字表,其中包含^ 2值的条目。因此,对于2(2),只有一个条目;对于三个(2和1),只有两个条目。这使我们不必每次都计算值。
首先,我们确定用户是否已登录。如果不是,则返回安全点的匿名授权。
接下来,我们使用JOIN来通过简单的EXISTS确定用户是否是与安全点相关的任何组的成员。如果不是,则返回与经过身份验证的用户关联的值。在我们的系统上,大多数匿名和经过身份验证的默认值都设置为1,因为我们要求我们属于特定的组。
Note: If an anonymous user gets a no access, the interface throws them over to a log in box to allow them to log in and try again.
如果用户是一个或者多个组的成员,则我们将从BitMask表中为这些组定义的每个值选择不同的值。例如,如果我们属于三个组,并且一个授权级别为8,一个授权级别为12,最后一个授权级别为36,则对位掩码表的选择将分别返回8、8和4,以及4和32. 通过执行不同操作,我们得到了数字4、8和32,它们正确地将掩码掩码为101100。
该值作为用户授权级别返回,并由网站处理。
有道理?
回答
我们使用按位运算。伪代码将类似于:
bool HasPermission(User user, Permission permission) { return (user.Permission & permission) != 0; } void SetPermission(User user, Permission permission) { user.Permission |= permission; } void ClearPermission(User user, Permission permission) { user.Permission &= ~permission; }
权限是我们帖子中定义的枚举类型,尽管它的任何类型都必须基于类似整数的类型。这同样适用于User.Permission字段。
如果这些运算符(&,| =和&=)对我们没有意义,请继续阅读按位运算(按位AND和按位OR)。