应用程序安全模型






3.75/5 (9投票s)
本文描述了一种简单、轻量级的方式来保护应用程序中的方法访问。
引言
本文描述了一种简单、易于管理且轻量级的方式来保护应用程序中的方法。
背景
最近,我一直在开发一个应用程序,其中一些部分(方法)需要得到保护,并且只对某些用户可用。该模型的要求还必须非常灵活和可移植,以便可以在独立应用程序和 Web 应用程序中使用。
其他解决方案
经过一番搜索,我找到了两个部分解决了我的问题。
.NET Framework 内置安全性
.NET Framework 提供了 PrincipalPermission
类来解决这个问题
public class MyClass
{
[PrincipalPermission(SecurityAction.Demand, Name = “Comp1\Administrator”)]
public void MyMethod()
{
}
}
当非管理员用户尝试访问此方法时,将抛出异常。默认情况下,特性本身不会在每个方法之前调用。它们是在反射给定程序集时调用的,并且这是由 .NET Framework 在此处完成的。
这工作正常,但存在一些限制
- 安全组(在我们的例子中是 *Comp1\Administrator*)必须是硬编码的,不能动态设置。
- 你必须使用 Microsoft 身份验证,这可能对,比如说,Mono 用户来说是个问题。
命令式调用
这就引出了第二个解决方案。你也可以通过在方法内命令式调用安全检查来以基本方式实现这一点
public class MyClass
{
public void MyMethod()
{
if(!IsPermited(MethodInfo.GetCurrentMethod(), User))
{
throw new NotAuthorizedException();
}
}
}
IsPermited
可以接受数据库中写入的授权值,并授权用户使用(或不使用)此 MyMethod
。包含安全值的表可能看起来像这样
ID | Method_Name | User_Id |
1 | MyClass.MyMethod |
1 |
这个解决方案的问题在于它非常难以管理,因为应用程序的安全部分的名称不是强类型的。例如,如果你想为新用户添加权限,你必须“手动”输入你安全方法的名称。这些值可以存储在另一个数据库表中或配置文件中,但它仍然可能导致应用程序中的数据不同步,因此是潜在的错误来源。
混合解决方案
第三种解决方案是将上述两种解决方案结合起来,创建一个“混合”方案。
我们将保留对安全方法的命令式调用,但是调用它的类和方法必须由我们的特定属性“签名”。该属性在调用 IsPermited
方法期间进行检查,如果调用来自“未签名”的方法,则会引发异常。
因此,现在 MyMethod
应该看起来像这样
public class MyClass
{
[MethodSecured]
public void MyMethod()
{
if(!IsPermited(MethodInfo.GetCurrentMethod(), User))
{
throw new NotAuthorizedException();
}
}
}
好的。那么如何管理权限呢?现在这是最简单的部分。我们要做的就是使用反射扫描程序集,并查找带有 MethodSecured
属性标记的方法。
然后,只需将方法分配给特定用户并将其放入数据库即可。
关于示例源代码的一些说明
该解决方案包含三个项目
SecuredLibrary
– 包含安全模型的基本引擎及其演示者。SecuredLibraryTest
– 包含SecuredLibrary
的测试。这是查看如何使用SecuredLibrary
程序集的最佳位置。SecurityManagementConsoleApplication
– 基本的控制台应用程序,仅作为SecuredLibrary
中演示者DisplayAllObjectsToSecurePresenter
的 GUI(视图)。该演示者使用反射来扫描程序集 SecuredLibrary.dll,以查找带有MethodSecuredAttribute
标记的方法。
所以,首先要做的是运行控制台应用程序,查看方法是如何列出的。然后运行
..\ApplicationSecurityModelExample\Projects\SecuredLibraryTest\bin\Debug\
SecuredLibraryTest.nunit (你需要 NUnit)。查看测试是如何构建的,以了解如何使用该引擎。最后,转到SecuredLibrary
项目,查看所有内容是如何在内部工作的(或者更好的是,调试它)。显示该应用程序的控制台。它建立在经典的 MVP(或者更确切地说是 VP,因为在这个例子中我没有使用 Model 来访问数据库)之上。
结论
我的解决方案可能不是最好的,但对我来说它工作得很好,因为它可以完全独立于任何内置的安全机制,并且因此可以非常轻松地进行迁移。
历史
- 2008 年 5 月 14 日:首次发布