C# 使用反射和枚举对MVC应用程序访问进行逻辑控制是否安全?
为了管理对网站的访问,我创建了一些必要的实体 目标是为我的MVC应用程序的某个控制器的操作方法使用自定义权限属性C# 使用反射和枚举对MVC应用程序访问进行逻辑控制是否安全?,c#,database,asp.net-mvc-3,reflection,enums,C#,Database,Asp.net Mvc 3,Reflection,Enums,为了管理对网站的访问,我创建了一些必要的实体 目标是为我的MVC应用程序的某个控制器的操作方法使用自定义权限属性 [Permissions(PermissionType.SomePermissionName, CrudType.CanDelete)] public ActionResult SomeAction() { } 对于此操作,我有两个枚举 [Flags] public enum CrudType { CanCreate = 0x1, CanRead = 0x2,
[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
enum中的某个命名常量从数据库中获取权限对象在这两种情况下,正确的工作取决于枚举与某些表字段或记录之间的关系。另一方面,我有一个很好的逻辑控制机制(在我看来)。
这样好吗 另一次编辑
在您的情况下,为
RolePermissions
类创建一个只读属性ExistingPermissions
,并在该属性getter中将四个布尔值合并为一个CrudType
。然后您就可以执行rp.ExistingPermissions.hasvag(permissionToCheck)
已编辑
感谢@DevDelivery指出了这个问题-很好。不幸的是,固定的解决方案并不像我希望的那样漂亮,所以在这种情况下,使用@DevDelivery的方法可能是有意义的
由于将CrudType
作为“位字段”,因此可以使用更简洁的方法(代码更少,可读性更好):
与您的解决方案相比的缺点是,如果您添加了更多操作(到现有的
CanRead
等),您将不得不修改此方法。使用反射会影响性能,并且后期绑定意味着更改枚举的名称
或属性将不会被编译器捕获
另外,这段代码很难理解,因此很难维护
这里只有4个选项可供检查。简单的switch语句更容易、更快、更干净
如果您试图允许对数据库进行更改或允许第三方组件引入新权限,则使用反射是有意义的。这在ASP.NET成员资格APi中不可用吗?我真的不喜欢成员资格。此外,我想使用我自己的类,自己的表,自己的控件等等,除了自己的类,自己的表,自己的控件之外,还有什么原因你不喜欢?当我考虑转到会员APi时:(好的。第一个原因。第二个原因-我很方便自己控制一切。当然这是一个品味的问题…哇。一个经过深思熟虑、陈述正确的问题,有正确的代码。现在这是一个好问题。我只希望我能给你一个好的答案…不幸的是,我的反应很弱。这里的问题是角色权限属性是布尔型的。或者,使用一组布尔型只会得到另一个布尔型。@DevDelivery-很好的捕获,这确实不起作用。修复后的解决方案似乎没有那么好。
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));
}