【问题标题】:Is it safe to use reflection and enums for logic control of MVC application access?使用反射和枚举进行 MVC 应用程序访问的逻辑控制是否安全?
【发布时间】:2011-12-17 11:38:23
【问题描述】:

试图管理对网站的访问我创建了一些必要的实体

目标是为我的 MVC 应用程序的某些控制器的操作方法使用自定义权限属性。

[Permissions(PermissionType.SomePermissionName, CrudType.CanDelete)]
public ActionResult SomeAction()
{
}

对于这个操作,我有两个枚举

[Flags]
public enum CrudType
{
    CanCreate = 0x1,
    CanRead = 0x2,
    CanUpdate = 0x4,
    CanDelete = 0x8,
}

[Flags]
public enum PermissionType
{
   SomePermissionName = 0x1,
   //... 
}

现在我想要下面的方法来检查权限

public static bool CanAccess(RolePermissions rp, CrudType crudType)
{
    var pInfo = rp.GetType().GetProperties();
    var res = pInfo.FirstOrDefault(x => x.Name == crudType.ToString());
    if(res != null)
    {
        return Convert.ToBoolean(res.GetValue(rp, null));
    }
    return false;
}

效果很好,但在这里使用反射是否安全?是不是很好的风格?
还有一个问题是关于这样一段代码

var permission = PermissionService.GetByName(permissionType.ToString());

在这里,我尝试使用PermissionType 枚举中的一些命名常量从数据库中获取权限对象。
在这两种情况下,正确的工作取决于枚举与某些表字段或记录之间的关系。另一方面,我有一个很好的控制逻辑的机制(在我看来)。 这是一个好方法吗?

【问题讨论】:

  • 这在 ASP.NET Membership APi 中不可用吗?
  • 我真的不喜欢会员资格。此外,我想使用自己的类、自己的表、自己的控件等
  • 除了自己的类、自己的表格、自己的控件之外,还有什么不喜欢的理由?当我想转向会员 APi :(
  • 好的。第一个原因here。第二个——我可以自己控制一切对我来说很方便。当然这是一个品味问题......
  • 哇。一个经过深思熟虑,陈述良好的问题,具有正确的代码。现在这是一个很好的问题。我只是希望我能给你一个好的答案......不幸的是,我的反射符很弱。

标签: c# database asp.net-mvc-3 reflection enums


【解决方案1】:

另一个编辑
在您的情况下,为RolePermissions 类创建一个只读属性ExistingPermissions 并在该属性getter 中将四个布尔值合并为一个CrudType 是有意义的。然后你就可以rp.ExistingPermissions.HasFlag(permissionToCheck)

已编辑

感谢@DevDelivery 指出问题 - 很好。不幸的是,固定的解决方案并不像我希望的那样漂亮,所以在这种情况下,使用@DevDelivery 的方法可能是有意义的。

由于您将CrudType 作为“位域”,因此您可以使用更简洁的方法(更少的代码和更好的可读性):

public static bool CanAccess(RolePermissions rp, CrudType permissionToCheck)
{
    CrudType existingPermissions = 
                                SetPermissionFlag(CrudType.CanCreate, rp.CanCreate) |
                                SetPermissionFlag(CrudType.CanRead, rp.CanRead) | 
                                SetPermissionFlag(CrudType.CanUpdate, rp.CanUpdate) |
                                SetPermissionFlag(CrudType.CanDelete, rp.CanDelete);

    return existingPermissions.HasFlag(permissionToCheck);
}

public static CrudType SetPermissionFlag(CrudType crudType, bool permission)
{
    return (CrudType)((int)crudType * Convert.ToInt32(permission));
}

与您的解决方案相比,缺点是您必须修改此方法以防添加更多操作(对现有的CanRead 等)。

【讨论】:

  • 这里的问题是 RolePermission 属性是布尔值。 Or'ing 一堆布尔值只会给你另一个布尔值。
  • @DevDelivery - 很好,这确实行不通。修复后似乎解决方案不是那么漂亮。
【解决方案2】:

使用反射会影响性能,而后期绑定意味着更改枚举的名称 或属性不会被编译器捕获。

另外,这段代码很难理解,因此也很难维护。

这里只有 4 个选项需要检查。一个简单的 switch 语句更容易、更快、更简洁。

如果您尝试允许对数据库进行更改或允许第三方组件引入新权限,则使用反射是有意义的。

【讨论】:

    猜你喜欢
    • 2010-09-22
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 2021-03-06
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多