【问题标题】:WindowsIdentity Impersonate method fails when impersonating an admin account模拟管理员帐户时,WindowsIdentity Impersonate 方法失败
【发布时间】:2014-07-10 05:20:47
【问题描述】:

我正在尝试在 .NET 控制台应用程序中模拟用户帐户,当它到达我调用 Impersonate() 方法的位置时,应用程序似乎立即退出。方法调用在 try-catch 块中,但它甚至从未到达 'catch' 块,所以我看不出错误是什么!

以下是相关代码:

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

然后在我的应用程序开始时:

bool returnValue = LogonUser(user, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref m_tokenHandle);
if (!returnValue)
{
    int ret = Marshal.GetLastWin32Error();
    throw new System.ComponentModel.Win32Exception(ret);
}
// Impersonate
WindowsIdentity _identity = new WindowsIdentity(m_tokenHandle);
EmailHelper.SendErrorMessage("Windows Identity Created!", string.Format("Created at: {0}", DateTime.Now.ToLongTimeString()));
try
{
    m_impersonatedUser = _identity.Impersonate();
    EmailHelper.SendErrorMessage("Impersonation Complete...", string.Format("Impersonation at: {0}", DateTime.Now.ToLongTimeString()));
}
catch
{
    int ret = Marshal.GetLastWin32Error();
    EmailHelper.SendErrorMessage("Error impersonating user!", string.Format("Error: {0}", ret));
}
finally
{
    EmailHelper.SendErrorMessage("Finally block executed?!", "What is going on?");
}

我收到了最初的“已创建 Windows 身份”电子邮件,但没有收到任何其他电子邮件!有谁知道我如何找出我的潜在错误以及为什么我的模拟不起作用?

谢谢!

编辑:

我尝试了这篇 MSDN 文章中的代码:http://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110).aspx,唯一的修改是在模拟时尝试创建文件。

修改正在更改此代码:

using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
{
    // Check the identity.
    Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);
}

收件人:

using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
{
    // Check the identity.
    Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);
    System.IO.File.CreateText(@"Test.txt");
}

我在以“标准”用户身份运行 exe 时得到的输出显示 LogonUser 成功,WindowsIdentity.GetCurrent().Name 返回模拟的用户名,但创建文件失败,错误代码为 1346,根据 MSDN , 是:

ERROR_BAD_IMPERSONATION_LEVEL 1346 (0x542) 未提供所需的模拟级别,或者提供的模拟级别无效。

这是什么意思?谷歌尚未对此有所了解...

编辑 2:

我可以使用此代码模拟另一个标准用户帐户,但是当我尝试模拟我的管理员帐户时它失败了。是否可以以某种方式更改代码以允许运行此 exe 的标准用户模拟管理员帐户?

【问题讨论】:

  • 请显示一些代码以揭示什么是“在使用中创建文件”。如果你写错了位置,或者使用了错误的代码,那么错误代码并不奇怪。
  • 嗨 Lex Li,我编辑了我的问题以显示我添加的代码。尝试模拟管理员帐户时,应用程序不会创建文件,而是将“模拟后”行写入控制台。
  • @dasboth:您可以退出 THAT PC 并使用您在代码中指定的确切用户名/密码登录吗? (即domain\userpassword)听起来您正在尝试使用PC 上尚不存在的帐户登录。 (???)
  • 我运行 Visual Studio 的帐户是我的管理员帐户,这是默认登录的帐户,也是我试图模拟的帐户。然后我切换用户并以我的“标准”用户身份登录,尝试进行模拟,然后失败并出现“ERROR_BAD_IMPERSONATION_LEVEL”错误。我尝试了登录类型和模拟级别的不同组合,但都无济于事。是否可能不支持冒充管理员帐户?

标签: c# .net impersonation


【解决方案1】:

当我运行您的代码时,我将所有发送呼叫的电子邮件替换为 Console.WriteLine,并使用我的 UPN 创建了 Windows 标识。这导致了对 try 块的调用,然后是 finally 块,正如预期的那样。

您的电子邮件发送方式可能存在问题。我会看看你在用Console.WriteLine() 替换后得到的结果是否相同。 还可以尝试在末尾添加Console.ReadLine(),这样您就可以在不退出应用程序的情况下查看发生了什么。可能是它工作正常,而您只是没有收到电子邮件。如果电子邮件工作正常,应用程序将立即退出,如果在那之后没有可调用的线路,但您仍然会收到一封电子邮件。

【讨论】:

  • 嗨 Savanna,感谢您对它进行测试。我应该提供一些上下文:此代码的目的是将一些文件从服务器复制到本地计算机,否则用户无法访问,因此我需要模拟以管理员身份复制文件。最初电子邮件代码不存在,而是写入日志文件,但我将其替换为电子邮件代码,因为我认为这是权限问题。无论哪种方式,在 Visual Studio 中运行代码都可以,但是当我得到我描述的行为时,部署它并以用户身份运行可执行文件。
  • 在我之前的评论中用完了字符。当我以用户身份运行可执行文件时,我收到了初始电子邮件,但没有收到其他邮件,甚至没有 finally 块中的邮件。
  • 日志文件正常工作,但仅在 Visual Studio 中运行时再次运行。以用户身份运行 exe 甚至没有创建日志文件,这就是为什么我用电子邮件代码替换它的原因,认为这是权限问题。我发布的代码位于类库中,而我正在运行的可执行文件实际上只调用该类库中的方法。这会有所作为吗?当您说您的 UPN 时,您是什么意思? LogonUser 正在返回 true,这是否意味着它已正确验证它?
  • 您可以通过几种方式创建 WindowsIdentity。 msdn.microsoft.com/en-us/library/… 我用一个代表我自己的用户名的字符串创建了这个。所以我在冒充自己。我不确定 m_tokenHandle 适合你。
  • 我猜令牌句柄是有效的,因为 LogonUser 返回成功(我也可以在事件查看器中看到登录成功)。我刚刚尝试使用 DuplicateToken 生成不同的令牌并使用它来创建 WindowsIdentity,这似乎做了完全相同的事情。
【解决方案2】:

你测试过m_tokenHandle吗?

if (m_tokenHandle != IntPtr.Zero)
{
  // continue on

你测试过_identity吗?也没有测试。

if (_identity != null)
{
  // continue on

无论 try 例程是否成功,finally 块都会执行。

【讨论】:

  • 您好 jp2code,我尝试添加一些代码来向我发送有关值的电子邮件,并且 m_tokenHandle 不等于 IntPtr.Zero 并且 _identity 也不为空。该代码在 Visual Studio(在我的管理员帐户下运行)中运行时有效(通过 try-catch),但在以用户身份执行时无效,我认为这是问题所在,但 finally 块中的代码没有执行,因为应用程序似乎没有走那么远!
  • 您可能需要让您的网络人员为您的 PC 设置一个管理员帐户。然后,在调用您的代码之前模拟该帐户。见How do you do Impersonation in .NET?
  • 我模拟的帐户是管理员帐户,但运行 exe 的帐户是标准用户帐户。也许用户帐户需要一些额外的权限才能让我的代码模拟管理员帐户?
【解决方案3】:

遗憾的是,这似乎仍然不起作用,我有一种预感,尝试使用 WindowsIdentity 模拟管理员帐户可能不受支持,或者我的方法有缺陷。无论哪种方式,相当虎头蛇尾,我决定完全采用不同的方法,并将我想以管理员身份运行的代码放入单独的可执行文件中,然后使用管理员凭据作为新进程启动该 exe。

System.Diagnostics.Process.Start(myExecutablePath, args, adminUsername, adminPassword, domainName);

这很好用,所以遇到此问题的任何人都可以使用此解决方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 2020-08-03
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多