答案:在基于 .NET 的应用程序中使用基于角色的安全设置
.NET Framework 在 System.Security.Principal 命名空间中提供了基于角色的安全设置实现,您可以用此实现来授权应用程序。要在 .NET Framework 中使用应用程序授权,请创建 IIdentity 和 IPrincipal 对象来表示用户。IIdentity 封装的是一个通过验证的用户,IPrincipal 则是用户标识和用户角色的组合。
图 4 显示了 IIdentity 和 IPrincipal 对象之间的关系。
图 4:IIdentity 和 IPrincipal 对象之间的关系
请注意图 4 中的以下几点: - IIdentity 对象是实现 IIdentity 类的实例。IIdentity 对象表示特定的用户。
- IIdentity 接口具有 Name、IsAuthenticated 和 AuthenticationType 属性。实现 IIdentity 的类通常还包含有特定用途的其他私有成员,例如,WindowsIdentity 类封装了正运行代码的用户的帐户令牌。
- IPrincipal 对象是实现 IPrincipal 的类的实例。IPrincipal 对象是代表用户的 IIdentity 及其具有的角色的组合。这样就可以实现单独的身份验证和授权。
- IPrincipal 对象使用 IsInRole 方法执行授权,并通过 Identity属性提供对 IIdentity 对象的访问。
使用标识
.NET Framework 提供了四种实现 IIdentity 接口的类:
- WindowsIdentity
- GenericIdentity
- PassportIdentity
- FormsIdentity
每种类都允许您使用不同种类的用户标识。要访问使用 Windows 身份验证的应用程序的当前
WindowsIdentity 对象,可以使用
WindowsIdentity 类的静态
GetCurrent 方法,如以下代码所示:
您还可以通过在自己定义的类中实现
IIdentity 接口来创建自定义标识类。有关创建自定义标识的详细信息,请参阅本指南后面的
扩展默认实现。有关如何使用默认
IIdentity 实现的详细信息,请参阅本指南后面的
设计用于授权的身份验证。
使用主体
.NET Framework 提供了链接用户角色和标识的
IPrincipal 接口。所有执行应用程序授权的托管代码都应该使用实现
IPrincipal 的类的对象。例如,
WindowsPrincipal 和
GenericPrincipal 类提供了内置的
IPrincipal 实现。另外,您也可以根据
IPrincipal 创建自己的自定义主体类。
为了提高编码效率,您可以使用本指南的
设计用于授权的身份验证一节中介绍的技术,通过使用
Thread 对象的静态
CurrentPrincipal 属性可以将
IPrincipal 对象链接到线程,这样当前线程就可以轻松地访问
IPrincipal 对象了,如以下代码所示:
然后,您可以测试用户是否属于某一特定的角色,从而执行授权检查。为此,可以使用
IPrincipal 接口的
IsInRole 方法,如以下代码所示:
ASP.NET 应用程序处理
IPrincipal 对象的方法与其他基于 .NET 的应用程序的处理方法有所不同。ASP.NET 通过无状态的 HTTP 协议创建会话外观。作为会话的一部分,执行用户请求的所有代码可以通过
HttpContext 对象的
User 属性,使用代表用户的
IPrincipal 对象。Global.asax 文件发生
OnAuthenticate 事件之后,公共语言运库使用
HttpContext.User 值自动更新
Thread.CurrentPrincipal。
ASP.NET 应用程序通常使用
User 属性执行授权检查,如以下代码所示:
注意:手动更改 HttpContext.User 将自动更新在同一 HTTP 上下文环境中执行的所有线程的 Thread.CurrentPrincipal。但是,改变 Thread.CurrentPrincipal 不会影响 HttpContext.User 属性,它只影响为请求中其余内容选择的线程。
有关创建自己的
IPrincipal 类型的详细信息,请参阅本指南后面的
扩展默认实现。有关如何使用默认
IPrincipal 实现的详细信息,请参阅本指南后面的
设计用于授权的身份验证。
授予使用 IIdentity 和 IPrincipal 对象的权限
使用
IIdentity 对象是一种敏感操作,因为在该操作中可以使用与用户相关的信息。允许应用程序更改当前的
IPrincipal 对象也应该受到保护,因为应用程序授权能力是以当前的主体为基础的。框架要求这些操作具有代码访问安全性权限,从而提供了保护。使用 Caspol.exe 或 .NET Framework 配置工具为需要管理这些对象的应用程序授予
SecurityPermissionAttribute.ControlPrincipal 权限。
默认情况下,所有本地安装的应用程序均具有该权限,因为它们是在“完全信任”的权限设置下运行的。
执行以下方法需要
ControlPrincipal 权限:
- AppDomain.SetThreadPrincipalPolicy()
- WindowsIdentity.GetCurrent()
- WindowsIdentity.Impersonate()
- Thread.CurrentPrincipal()
有关使用 CASPOL 设置安全权限的详细信息,请参阅 MSDN Library 中的
Configuring Security Policy Using the Code Access Security Policy Tool (Caspol.exe)(英文)。
Windows 和公共语言运库之间管理授权的区别
公共语言运库在 Windows 安全结构之上有一个单独的安全结构。Windows 线程具有 Windows 授权用户的令牌,而运行时线程具有代表该用户的
IPrincipal 对象。
因此,在开发代码时,必须至少考虑两种代表用户的安全上下文。例如,设想一个使用窗体身份验证的 ASP.NET 应用程序:默认情况下,ASP.NET 进程在名为“ASPNET”的 Windows 服务帐户(专为应用程序创建的用户帐号)下运行。假设有一位名为
Bill 的用户登录到 Web 站点。
Thread.CurrentPrincipal 属性代表窗体身份验证的用户 Bill。公共语言运库看到以 Bill 运行的线程,于是所有托管代码都将 Bill 看作主体。如果托管代码要求访问系统资源(如文件),则不管
Thread.CurrentPrincipal 的值如何,非托管代码都可以看到 ASPNET Windows 服务帐户。图 5 说明了公共语言运库和操作系统线程之间的授权关系。
图 5:公共语言运库和操作系统线程之间的授权关系模拟允许您改变操作系统线程在与 Windows 的交互过程中执行的用户帐户。可以通过调用
WindowsIdentity.Impersonate 方法模拟 Windows 标识。这种模拟形式允许您作为特定用户访问本地资源。当调用
Impersonate 方法时,您就以
WindowsIdentity 所代表的用户登录。您必须有权访问服务器中的用户凭据且有权调用
LogonUser API。但是,手动创建
WindowsIdentity 的过程比较复杂,因此,如果不是十分必要,最好不要执行模拟。
当应用程序代码模拟其他用户之后,
WindowsImpersonatationContext.Undo 方法将用户标识还原到原始标识。这些函数一般必须成对调用,如以下代码所示:
有关模拟 Windows 帐户的详细信息,请参阅 MSDN Library 中的
Impersonating and Reverting(英文)。
注意:在 Windows 2000 中,调用 LogonUser API 的进程必须具备 SE_TCB_NAME 特权。有关验证用户凭据的详细信息,请参阅文章 Q180548 HOWTO: Validate User Credentials on Microsoft Operating Systems(英文),位于 Microsoft Knowledge Base(英文)中。
设计用于授权的身份验证
授权取决于身份验证,也就是说,必须对用户或过程进行身份验证,然后才能对其授权,以便查看或使用受保护的资源。本节将分析两种身份验证机制并阐述这两种机制对授权的影响:
- 根据 Windows 身份验证执行授权
- 根据非 Windows 身份验证执行授权
选择哪种身份验证机制通常受与授权无关的因素的影响,例如 Windows 用户帐户的可用性以及一些常见的环境问题,包括客户端的浏览器类型。但是,您选择的身份验证机制确实会影响您执行授权的方式。
根据 Windows 身份验证执行授权
所有应用程序在称为“Windows 标识”的 Windows 用户帐户下执行。在 Windows 身份验证过程中,您将使用这种 Windows 用户帐户或 Wi
上一个:使用DES加密解密代码(C# & vb.Net),已经调试成功,支持中文加解密,公布!
下一个:设计由应用程序管理的授权