c# - 模拟和 DirectoryEntry

标签 c# impersonation directoryentry

我成功地模拟了一个用户帐户,但我无法使用模拟帐户绑定(bind)到 AD 并拉下 DirectoryEntry

下面的代码输出:

  • 在模拟之前我是:DOMAIN\user
  • 模拟后我是:DOMAIN\admin
  • 错误:C:\Users\user\ADSI_Impersonation\bin\Debug\ADSI_Impersonation.exe samaccountname:

我的问题似乎类似于:

How to use the System.DirectoryServices namespace in ASP.NET

我正在获取一个主要 token 。我知道我需要使用委托(delegate)才能在远程计算机上使用模拟 token 。我确认该帐户没有选中“帐户是敏感的,不能被委托(delegate)”的标志。我还确认本地组策略和域组策略不会阻止委派:

计算机配置\Windows 设置\安全设置\本地策略\用户权限分配\

我错过了什么?

谢谢!

using System;
using System.DirectoryServices;
using System.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;

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

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

        static void Main(string[] args)
        {
            const int LOGON32_PROVIDER_DEFAULT = 0;
            const int LOGON32_LOGON_INTERACTIVE = 2;

            string userName = "admin@domain.com";
            string password = "password";

            Console.WriteLine("Before impersonation I am: " + WindowsIdentity.GetCurrent().Name);

            SafeTokenHandle safeTokenHandle;

            try
            {
                bool returnValue = LogonUser(userName, null, password,
                    LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                    out safeTokenHandle);

                if (returnValue)
                {
                    WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
                    WindowsImpersonationContext impersonatedUser = newId.Impersonate();
                }
                else
                {
                    Console.WriteLine("Unable to create impersonatedUser.");
                    return;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Authentication error.\r\n" + e.Message);
            }

            Console.WriteLine("After impersonation I am: " + WindowsIdentity.GetCurrent().Name);

            string OU = "LDAP://dc=domain,dc=com";
            DirectoryEntry entry = new DirectoryEntry(OU);
            entry.AuthenticationType = AuthenticationTypes.Secure;

            DirectorySearcher mySearcher = new DirectorySearcher();
            mySearcher.SearchRoot = entry;
            mySearcher.SearchScope = System.DirectoryServices.SearchScope.Subtree;
            mySearcher.PropertiesToLoad.Add("cn");
            mySearcher.PropertiesToLoad.Add("samaccountname");

            string cn = "fistname mi. lastname";
            string samaccountname = "";

            try
            {
                // Create the LDAP query and send the request
                mySearcher.Filter = "(cn=" + cn + ")";

                SearchResultCollection searchresultcollection = mySearcher.FindAll();

                DirectoryEntry ADentry = searchresultcollection[0].GetDirectoryEntry();

                Console.WriteLine("samaccountname: " + ADentry.Properties["samaccountname"].Value.ToString());
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + e.Message);
            }

            Console.WriteLine("samaccountname: " + samaccountname);
            Console.ReadLine();
        }
    }

    public 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);
        }
    }
}

最佳答案

许多 .NET API 没有考虑您的手动模拟,例如您注意到的 LDAP 查询。因此,您需要改用 DirectoryEntry 的重载构造函数,

http://msdn.microsoft.com/en-us/library/bw8k1as4.aspx

http://msdn.microsoft.com/en-us/library/wh2h7eed.aspx

关于c# - 模拟和 DirectoryEntry,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8957886/

相关文章:

c# - xUnit.net 理论,其中 MemberData 来自派生类

security - 当前用户是LocalSystem 检查?

c++ - ImpersonateLoggedOnUser 成功但辅助进程仍在初始上下文中运行

c# - 使用 C# 更改 AD 用户终端服务器属性

directoryentry - 给定用户的 SID,我如何获取 AD DirectoryEntry?

c# - 使用 "DirectoryEntry"API 从远程计算机通过 ssl 连接到 LDAP

c# - 返回 linq 查询的结果,但修改了一个值

c# - 如何在 Unity 中使用 UI.Text 作为预制件?

c# - 如何声明返回 "anything"的泛型集合的方法 (C#)

.net - 如何在模拟 Windows 服务时调用 net.pipe(命名管道)WCF 服务