【问题标题】:What is the best way to handle multiple permission types?处理多种权限类型的最佳方法是什么?
【发布时间】:2010-09-05 07:30:08
【问题描述】:

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

场景

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

过去,我选择了以下两种我知道的方法之一。

  1. 使用具有特殊列的单个权限表,用于 确定如何应用参数。中的特殊列 这个例子是TypeIDTypeAuxID。 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
    

我的想法

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

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

【问题讨论】:

    标签: sql permissions


    【解决方案1】:

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

    就个人而言,我有时会使用带标记的权限枚举。这样您就可以对枚举项使用 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 个角色的值为 2^6 = 64,而 31 个角色的值为 2^31 = 2,147,483,647,这是最大 int 值。所以在 T-SQL 中可以使用的最大数据类型是bigint (2^63)。当然你可以使用varchar类型,但是当我有很多角色时,我更喜欢使用John Downey的解决方案。
    【解决方案2】:

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

    对不起,如果我没有回答你的问题,我就像有人问 vb 问题时说要学习 c# 的人。

    【讨论】:

      【解决方案3】:

      除了 John Downey 和 jdecuyper 的解决方案之外,我还在位域的末尾/开头添加了一个“Explicit Deny”位,以便您可以按组、角色成员执行附加权限,然后根据权限减去根据明确的拒绝条目,就像 NTFS 一样,权限方面的工作。

      【讨论】:

        【解决方案4】:

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

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

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

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

        【讨论】:

          【解决方案5】:

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

          • 用户 - 这很简单,它是典型的用户表
          • 组 - 这将是您部门的代名词
          • 角色 - 这是一个具有所有权限的表,通常还包括人类可读的名称和描述
          • Users_have_Groups - 这是一个用户所属组的多对多表
          • Users_have_Roles - 另一个多对多表,其中列出了分配给单个用户的角色
          • Groups_have_Roles - 每个组具有哪些角色的最终多对多表

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

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

          【讨论】:

            猜你喜欢
            • 2021-03-01
            • 2016-05-26
            • 2016-05-17
            • 2014-06-25
            • 2022-10-09
            • 2011-02-26
            • 2015-05-31
            • 1970-01-01
            • 2010-09-06
            相关资源
            最近更新 更多