【问题标题】:IIS impersonation returns app pool userIIS 模拟返回应用程序池用户
【发布时间】:2013-03-20 07:21:15
【问题描述】:

我正在编写一个应用程序,允许用户管理 Active Directory 中的组。我想使用当前登录用户的身份,这样他们就不必登录应用程序。该应用程序远程工作没有问题,但在部署到测试服务器(Windows 2008R2 IIS6)后,它试图使用 IIS APPPOOL 身份而不是我的身份。

相关的 web.config 设置:

<authentication mode="Windows"></authentication>
<identity impersonate="true" />

身份验证代码:

Session("Username") = ActiveDirectory.GetUsername( _
    WindowsIdentity.GetCurrent.User.Translate(GetType(NTAccount)).Value _
)

ActiveDirectory 是一类辅助函数,不包含任何模拟逻辑。

如何获取访问应用程序的用户而非 IIS APPPOOL 用户的身份?

【问题讨论】:

  • 什么类型的用户在管理组......?这是任何用户..?如果是这样BAD IDEA 你为什么没有一个 AD Admin 组来管理它..?还有另一件事,您仍然可以获取机器的当前用户并将其保留在不同的会话中,然后再解析为您尝试模拟的服务帐户或帐户用户..
  • 只有组管理员才能编辑成员资格。在解析为服务帐户之前,我如何访问当前机器的用户?
  • var currUser= System.Security.Principal.WindowsIdentity.GetCurrent().Name.Split('\\');
  • 那么您可以使用这段代码来确定用户是否甚至处于 AD 中,例如 PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "MachineIP:389", "dc=dom,dc=fr", "jpb", "root.123"); 或使用 PrincipalContext
  • 确保匿名身份验证已关闭

标签: c# vb.net iis iis-6 impersonation


【解决方案1】:

我相信应用程序将以应用程序池的身份运行。为了以不同的身份运行,您需要模拟用户。 MSDN 有一篇关于它的文章。这是我根据帮助我完成类似事情的文章编写的课程。

class Impersonator : IDisposable
  {
      [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
      private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
          int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

      [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
      private extern static bool CloseHandle(IntPtr handle);

      WindowsIdentity newId;
      WindowsImpersonationContext impersonatedUser;
      private bool isDisposed;

      public Impersonator(string user, string password, string domain)
      {
          SafeTokenHandle safeTokenHandle;
          const int LOGON32_PROVIDER_DEFAULT = 0;
          //This parameter causes LogonUser to create a primary token. 
          const int LOGON32_LOGON_INTERACTIVE = 2;

          // Call LogonUser to obtain a handle to an access token. 
          bool returnValue = LogonUser(user, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);

          newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
          impersonatedUser = newId.Impersonate();
      }

      public void Dispose()
      {

          this.Dispose(true);
          GC.SuppressFinalize(this);
      }

      public void Dispose(bool disposing)
      {
          if (!this.isDisposed)
          {
              if (disposing)
              {
                  if (impersonatedUser != null)
                  {
                      this.impersonatedUser.Dispose();
                  }

                  if (newId != null)
                  {
                      this.newId.Dispose();
                  }
              }
          }

          this.isDisposed = true;
      }

      ~Impersonator()
      {
          Dispose(false);
      }

      private sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
      {
          private SafeTokenHandle()
              : base(true)
          {
          }

          [DllImport("kernel32.dll")]
          [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
          [SuppressUnmanagedCodeSecurity]
          [return: MarshalAs(UnmanagedType.Bool)]
          private static extern bool CloseHandle(IntPtr handle);

          protected override bool ReleaseHandle()
          {
              return CloseHandle(handle);
          }
      }
  }

当您想模拟用户并在完成后处置该类时,基本上创建该类的一个新实例。

我希望这会有所帮助!

【讨论】:

  • 感谢 MisterXero 的评论。这看起来像您需要用户名和密码,对吗?我希望在不让他们再次登录的情况下模拟登录到正在访问该站点的任何计算机的用户。
  • 在我的应用程序中,我有一个单独的帐户可以访问我用来更改身份的活动目录(只有我知道用户名和密码)。我会通过 System.Web.HttpContext.Current.User.Identity 找到当前用户。一旦我更改了应用程序的身份并知道了用户,我就可以在 AD 中查找用户,看看他们是否有权更改 AD。如果他们这样做了,那么就可以继续执行您需要对 AD 执行的任何操作。
【解决方案2】:

我不确定这是否符合您想要做的事情。但是要检索一个用户,你会使用这样的东西:

WindowsIdentity user = WindowsIdentity.GetCurrent();
WindowsPrincipal role = new WindowsPrincipal(user);

通过上述解决方案,您也可以实际检查角色,或定义Identity.Name 为您提供信息。

另一种解决方案:

Environment.UserName;
Environment.GetEnvironmentVariable("USERNAME");

现在我知道WindowsIdentity 将跨越一个,但其他我不确定他们将如何处理Active Directory。因此,您可能需要对 域上下文 做一些事情。

// Define Context
PrincipalContext context = new PrincipalContext(ContextType.Domain);

// Find User
UserPrincipal user = UserPrincipal.Current;

// Check User
if (user != null)
{
    string loginName = user.SamAccountName; // Whatever "Login Name Means"
}

这里也有很好的资源:

Managing Directory Security:

MSDN Docs On Account Management

不确定这是否正是您的意思,但希望对您有所帮助。

【讨论】:

  • 感谢格雷格的回答;不幸的是,环境变量正在返回与应用程序池或服务器相关的结果,而不是我的帐户。基本上,我只是想查看 正在访问该页面,而无需让他们再次登录该站点,方法是查看谁登录了他们正在使用的计算机。
  • @PhillipCopley 是的,我就是这么想的。定义 Context 可能是一个不错的选择,然后可能会满足您的需求。对不起,我不能提供更多帮助。我看看能不能帮你解决。
猜你喜欢
  • 1970-01-01
  • 2014-10-01
  • 2011-09-20
  • 1970-01-01
  • 1970-01-01
  • 2021-10-14
  • 2011-03-10
  • 1970-01-01
相关资源
最近更新 更多