我经常遇到以下场景,我需要提供许多不同类型的权限。我主要使用 ASP.NET / VB.NET 和 SQL Server 2000。

设想

我想提供一个可以处理不同参数的动态权限系统。假设我想授予某个部门或特定人员访问应用程序的权限。并假设我们有许多不断增长的应用程序。

过去,我选择了以下两种我所知道的方法之一来做到这一点。

  1. 使用单个权限表,其中包含用于确定如何应用参数的特殊列。此示例中的特殊列是TypeID和TypeAuxid。SQL看起来像这样。

    SELECT COUNT(PermissionID)
    FROM application_permissions
    WHERE
    (TypeID = 1 AND TypeAuxID = @UserID) OR
    (TypeID = 2 AND TypeAuxID = @DepartmentID)
    AND ApplicationID = 1
    
  2. 对每种类型的许可使用映射表,然后将它们全部加入。

    SELECT COUNT(perm.PermissionID)
    FROM application_permissions perm
    LEFT JOIN application_UserPermissions emp
    ON perm.ApplicationID = emp.ApplicationID
    LEFT JOIN application_DepartmentPermissions dept
    ON perm.ApplicationID = dept.ApplicationID
    WHERE q.SectionID=@SectionID
      AND (emp.UserID=@UserID OR dept.DeptID=@DeptID OR
     (emp.UserID IS NULL AND dept.DeptID IS NULL)) AND ApplicationID = 1
    ORDER BY q.QID ASC
    

我的想法

我希望这些例子有意义。我把它们拼凑在一起。

第一个示例需要较少的工作,但它们都不是最佳答案。有更好的方法来处理这个问题吗?

有帮助吗?

解决方案

我同意约翰·唐尼的观点。

就我个人而言,我有时会使用标记的权限枚举。这样您就可以对枚举项使用 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) 来验证用户是否具有特定权限。

其他提示

我通常对权限系统进行编码的方式是使用 6 个表。

  • 用户 - 这非常简单,这是典型的用户表
  • 群组 - 这将是您的部门的同义词
  • 角色 - 这是一个包含所有权限的表,通常还包括人类可读的名称和描述
  • Users_have_Groups - 这是一个用户所属组的多对多表
  • Users_have_Roles - 另一个多对多表,其中显示分配给单个用户的角色
  • Groups_have_Roles - 每个组拥有的角色的最终多对多表

在用户会话开始时,您将运行一些逻辑来提取他们分配的每个角色,无论是目录还是通过组。然后,您可以针对这些角色进行编码作为您的安全权限。

就像我说的,这是我通常做的事情,但你的情况可能会有所不同。

除了 John Downey 和 jdecuyper 的解决方案之外,我还在位字段的末尾/开头添加了“显式拒绝”位,以便您可以按组、角色成员资格执行附加权限,然后根据显式拒绝减去权限条目,就像 NTFS 的工作方式一样,需要许可。

老实说,ASP.NET 成员资格/角色功能非常适合您描述的场景。编写自己的表/过程/类是一项很好的练习,您可以很好地控制微小的细节,但在我自己这样做之后,我得出的结论是最好只使用内置的 .NET 东西。许多现有代码都是为了解决这个问题而设计的,这很好。我从头开始编写花了大约两周的时间,而且它远没有 .NET 那样强大。您必须编写大量垃圾代码(密码恢复、自动锁定、加密、角色、权限接口、大量过程等),而时间可以更好地花在其他地方。

抱歉,如果我没有回答你的问题,我就像有人问 vb 问题时说要学习 c# 的人一样。

我在各种应用程序中使用的方法是使用一个通用 PermissionToken 类,该类具有可更改的 Value 属性。然后,您查询所请求的应用程序,它会告诉您需要哪些 PermissionToken 才能使用它。

例如,运输应用程序可能会告诉您它需要:

new PermissionToken()
{
    Target = PermissionTokenTarget.Application,
    Action = PermissionTokenAction.View,
    Value = "ShippingApp"
};

这显然可以扩展到创建、编辑、删除等,并且由于自定义值属性,任何应用程序、模块或小部件都可以定义自己所需的权限。YMMV,但这对我来说一直是一种有效的方法,我发现它可以很好地扩展。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top