Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在ASP.NET MVC中使用SQL中基于[Flags]的枚举到int权限管理进行访问控制_C#_Sql_Sql Server 2008_Enums_Enum Flags - Fatal编程技术网

C# 在ASP.NET MVC中使用SQL中基于[Flags]的枚举到int权限管理进行访问控制

C# 在ASP.NET MVC中使用SQL中基于[Flags]的枚举到int权限管理进行访问控制,c#,sql,sql-server-2008,enums,enum-flags,C#,Sql,Sql Server 2008,Enums,Enum Flags,这个问题的灵感来自于ASP.NET MVC。在这里,我试图将公认的答案转化为切实可行的解决方案 答案提到使用FileSystemSecurity作为管理权限的灵感。在这里,我还使用带有Flags属性的enum来定义我所有对象的ACL。此外,我的对象的每个成员都将存储在SQL中的一列中。假设一个简化的Linq2SQL、EF或nHibernate ORM映射 编辑:添加了此方法的以下优点/基本原理 此安全模型的灵感来自管理文件级权限的.NET方法 我喜欢这种方法的一个主要原因是,我可以通过将所有AC

这个问题的灵感来自于ASP.NET MVC。在这里,我试图将公认的答案转化为切实可行的解决方案

答案提到使用
FileSystemSecurity
作为管理权限的灵感。在这里,我还使用带有Flags属性的enum来定义我所有对象的ACL。此外,我的对象的每个成员都将存储在SQL中的一列中。假设一个简化的Linq2SQL、EF或nHibernate ORM映射

编辑:添加了此方法的以下优点/基本原理

此安全模型的灵感来自管理文件级权限的.NET方法

我喜欢这种方法的一个主要原因是,我可以通过将所有ACL合并在一起,轻松创建所有权限的摘要。我还喜欢添加拒绝ACL以删除继承的权限

List<myObject> PermissionsList  = GetACLForObject(ItemID, UserID);
foreach (var acl in PermissionsList)
{
   // The following enum has the [FlagsAttribute] applied so the .ToString() is pretty 
   PermissionWithFlagsEnum sampleForSO = (PermissionWithFlagsEnum )acl.Permission;

   Console.Writeline ("Setting " + sampleForSO.ToString() + " permission for group: " + acl.ACLName);

   ResultingPermission = resultPermission |  acl.Permission ; 
}
public int ResultingPermission {get;set;}
我有一个将用户ID连接到特定于对象的ACE的。这将减少对特定行的并发更新的需要。

问题

  • 这是个好主意吗

  • 以前有人做过吗(比这更好)?(编辑:)

  • 如果这是实现权限的标准方式,那么它叫什么


一般来说,将多个值(标志)放入单个字段是一个坏主意

如果您计划审核此数据,这是一个非常糟糕的主意,因为很难有效地挑出哪些标志在更新之间发生了更改

即使不进行审计,也可能会遇到问题

  • 许多简单的查询(删除此身份验证的用户)不是 因为之前需要执行位运算 比较

  • 另外
    从权限中选择用户<
    DBAceessRights.DetailRead可能不会返回正确的结果,因为
    
    AppearInListing&CreateNew
    大于DetailRead,但不大于 打开DetailRead。所以你希望得到的好处可能无法实现

  • 管理并发(多个写入程序到ACL)更加困难,因为改变一个“逻辑值”实际上就是改变所有的值


一般来说,将多个值(标志)放入单个字段是一个坏主意

如果您计划审核此数据,这是一个非常糟糕的主意,因为很难有效地挑出哪些标志在更新之间发生了更改

即使不进行审计,也可能会遇到问题

  • 许多简单的查询(删除此身份验证的用户)不是 因为之前需要执行位运算 比较

  • 另外
    从权限中选择用户<
    DBAceessRights.DetailRead可能不会返回正确的结果,因为
    
    AppearInListing&CreateNew
    大于DetailRead,但不大于 打开DetailRead。所以你希望得到的好处可能无法实现

  • 管理并发(多个写入程序到ACL)更加困难,因为改变一个“逻辑值”实际上就是改变所有的值

    • 我会说不

    • 您假设您需要的权限不超过32个(如果使用
      bigint
      ,则为64个)。对我来说,这听起来像是一个任意的限制。在数据库中移动到
      varbinary
      可以克服这一问题,但是您的枚举就麻烦了(无法在
      byte[]
      上创建枚举)!你将无法进行数字比较

    • 您假设特权
      0x1
      在逻辑上总是小于
      0x2
      0x80
      ,依此类推。在我的经验中,这种情况很少发生。更常见的情况是,权限相互独立(即:“添加用户”权限与“上传图像”权限无关;一组用户(管理员)拥有前者,而其他用户(内容发布者)拥有后者。这意味着您的数字比较没有您最初认为的那么有用

    • 您所做的可能会带来性能方面的好处,但您还没有证明存在性能问题!大多数我的权限系统使用每个用户一条数据库记录来授予或拒绝每个权限。获取100条记录不会对我的数据库征税。与usi相比,您最好在请求之间缓存每个用户的权限正在使用位掩码

    • 关于更新性能:用户权限多久更改一次?根据我的经验,一旦系统就位,它们往往是相当静态的

    • 我发现,当试图将大量数据打包到一个小空间中时,位掩码最有用。但是,当我最终拥有超过64件东西时,我的第1点常常会反过来咬我

      请注意,我在记录用户操作的统计信息(跟踪用户在搜索中找到的项目、查看的实体等)时使用了这种技术。我的原因纯粹是为了确保数据库记录长度固定且较小,因此插入速度较快。我没有做数字比较。(平心而论,我从未测试过
      int
      列和几个
      bit
      列之间是否存在任何差异)

      编辑 一个基本的选择(我正在使用):用户和权限(我称之为权限)之间的m:N关系

      (很抱歉我的用户有米老鼠耳朵!)

      UserRight
      中有记录表示该用户被授予了权限。没有记录表示没有权限。此查询提供了分配给用户的所有权限

      SELECT [dbo].[User].Username, [dbo].[Right].Id, [dbo].[Right].Name
      FROM [dbo].[Right]
      INNER JOIN [dbo].[UserRight] ON [dbo].[Right].Id = [dbo].[UserRight].RightId
      INNER JOIN [dbo].[User] ON [dbo].[User].Id = [dbo].[UserRight].UserId
      WHERE [dbo].[User].Id = @pUserId
      
      然后,在代码中声明用户有权:

      var grantedRights = RunTheAboveQuery(currentUser.Id);
      if (grantedRights.Any(r => r.Id == requiredRight))
          // User has the right.
      else
          // User does not have the right. 
      
      显然,您可以扩展它来检查一个用户在一个查询中拥有多个权限

      这并没有人为地限制系统支持的特权数量,也没有假设特权之间存在任何关系(所以你不能进行数字比较,一切都是如此)
      var grantedRights = RunTheAboveQuery(currentUser.Id);
      if (grantedRights.Any(r => r.Id == requiredRight))
          // User has the right.
      else
          // User does not have the right.