代码改变世界

安全探索——.NET 中的角色安全(1)

2009-02-17 14:31  G yc {Son of VB.NET}  阅读(593)  评论(0编辑  收藏

    (写在之前,很久没有写东西。原因吗,应该是我太迷茫了。在毕业之后,就有这个现象了,现在也是。在成为无业游民后,整天无所事事。因此,写出本文,一是复习一下自己学过的(也有新的),二是为自己准备一个目标。好努力一下)

.NET Framework出来有段时间了,也逐渐壮大了,自然安全性也是必不可少的。本文将说说.NET中的角色安全,也是本人最近学习总结的。(欢迎大家评论和指正)

说道基于角色的安全,.NET 中有2个主要的类型来支持这个,即 IIdentity 接口IPrincipal 接口

 

IIdentity 接口 是标识对象的基础接口,包含3个属性:访问名称的 Name 和 身份验证类型的 AuthenticationType 以及一个表示用户是否通过验证的IsAuthenticated。

IPrincipal 接口 是主体对象的基础接口,包含一个 Identity 属性,用于访问关联的 Identity 对象。和一个 IsInRole 方法,用于确定 Principal 对象所标识的用户是否为给定角色的成员。

 

上面2个体到的都是借口,实际用到是实现的类,后面也有介绍。

 

恩,说道这里,大家可能还不知道 标识对象 和 主体对象 是什么。我简单说明一下:

标识对象封装有关正在验证的用户或实体的信息。至少标识对象包含名称和身份验证类型。(可以通过自定义实现接口类扩充,下同)

主体对象表示代码运行时所在的安全上下文。主要包含了主体对象和关联的(多个)角色。

 

(如果对这些词汇不明白,可以参考MSDN上的文章 安全性的基础概念

 

说完了主体对象,在说说主体,主体表示一个用户的标识和角色,并代表此用户操作。 .NET Framework 中基于角色的安全性支持三种主体:  

  • 一般主体表示独立于 Windows NT 和 Windows 2000 用户和角色存在的用户和角色。
  • Windows 主体表示 Windows 用户及其角色(或其 Windows NT 和 Windows 2000 组)。Windows 主体可模拟其他用户,这意味着此类主体在表示属于某一用户的标识的同时,可代表此用户访问资源。
  • 自定义主体可由应用程序用该应用程序所需的任何方式定义。

好了,到此为止,基本内容介绍完了。这就要结束了吗?恩,实际上我很想的,不过怕板砖飞来,实际上也没有结束(PS,即使上面那点,我也用了N就才憋出来,唉。。。。没有写作才能)。

 

WindowsIdentity类 和 WindowsPrincipal 类

 

这2个类使用来表示 Windows 用户 和 Windows 组成员身份的。

有关这2个类的详细信息,请参考 MSDN WindowsIdentity 类 WindowsPrincipal 类)

 

使用 WindowsPrincipal 对象,有两种创建 WindowsPrincipal 对象的方法,使用的哪个取决于代码是必须重复执行基于角色的验证还是只需执行一次验证。

 

如果代码必须重复执行基于角色的验证,则以下过程中的第一个过程产生的系统开销较小。如果代码只需进行一次基于角色的验证,则可通过使用以下过程中的第二个过程来创建 WindowsPrincipal 对象。

 

方法1:

 

1、调用AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal) ,将当前程序设置 Windows 主体策略。(也可以调用VB的 My.User.InitializeWithWindowsUser() 方法。不过这个方法对多线程有兼容问题。WinForms 没有问题。)

2、通过 Thread.CurrentPrincipal 获取主体,也可以根据需要,转换类型 Dim MyPrincipal As WindowsPrincipal = CType(Thread.CurrentPrincipal, WindowsPrincipal) 。

 

方法2:

 

1、通过调用静态 WindowsIdentity.GetCurrent 方法初始化新的 WindowsIdentity 对象。
          Dim MyIdentity As WindowsIdentity = WindowsIdentity.GetCurrent()

2、创建一个新的 WindowsPrincipal 对象,并将在前面的步骤中创建的 WindowsIdentity 对象的值传递给该对象。
          Dim MyPrincipal As New WindowsPrincipal(MyIdentity)

     

    提示:在.NET 2.0 之后的VB中,可以使用My.User 来快速访问。My.User 中主要包含 :

    名称

    说明

    CurrentPrincipal

    获取或设置当前主体(对基于角色的安全性而言)。
    IsAuthenticated 获取一个值,该值指示是否验证了用户。
    Name 获取当前用户的名称。
    InitializeWithWindowsUser 将线程的当前主体设置为启动应用程序的 Windows 用户。

    使用方法,和上面的类似,主要代替了Thread.CurrentPrincipal。

    提示:在使用字符串检测Windows内置组的时候,需要在组名前面加 “BUILTIN\”,像这样 “BUILTIN\Administrators”

     

模拟与恢复

模拟是指当前用户 使用另外一个帐户的标记进行某个操作并并再次恢复到原先的帐户。

1、通过调用非托管的 LogonUser 方法,检索特定用户的帐户标记。此方法不在 .NET Framework 基类库中,而在非托管 advapi32.dll 中。具体参考代码

2、创建 WindowsIdentity 类的一个新实例,并向其传递标记。 
          Dim ImpersonatedIdentity As New WindowsIdentity(hToken)

3、创建 WindowsImpersonationContext 类的一个新实例,并用已初始化类的 WindowsIdentity.Impersonate 方法对其进行初始化以开始模拟。 
          WindowsImpersonationContext MyImpersonation = ImpersonatedIdentity.Impersonate()

4、当不再需要模拟时,调用 WindowsImpersonationContext.Undo 方法还原模拟。 
           MyImpersonation.Undo()

有关WindowsImpersonationContext 类 的详细信息,可以参考MSDN WindowsImpersonationContext 类

     

    clip_image004

    clip_image005

    clip_image006

    clip_image007

    注意:

    在 Windows Vista 中,用户帐户控制 (UAC) 确定用户的特权。如果您是内置管理员组的成员,将会给您分配两个运行时访问标记:标准用户访问标记和管理员访问标记。默认情况下,您拥有标准用户角色。当您尝试执行需要管理特权的任务时,可以使用“同意”对话框动态提升自己的角色。执行 IsInRole 方法的代码不显示“同意”对话框。如果您拥有标准用户角色,即使您属于内置管理员组,代码也会返回 false。您可以在执行代码前提升自己的特权,方法是右击应用程序图标,然后指示您需要以管理员身份运行它

    如果不使用管理员身份开打的,结果是这个样子

    clip_image008

     

     

程序代码