代码之家  ›  专栏  ›  技术社区  ›  Peter

使用WinNT://provider和目录服务连接到远程计算机会忽略用户名/密码

  •  3
  • Peter  · 技术社区  · 15 年前

    我正在使用DirectoryServices和WinNT://provider连接到远程计算机。然后我检查一些组成员信息,并可能从指定的本地组中添加或删除域用户。

    代码:

        string strUserPath = "WinNT://DomainName/someuser,user";
        DirectoryEntry deComputer = new DirectoryEntry("WinNT://" + Computername + ",computer");
        deComputer.RefreshCache();
        DirectoryEntry deGroup = deComputer.Children.Find("administrators", "group");
    
        IEnumerable members = deGroup.Invoke("members", null);
        List<DirectoryEntry> r = new List<DirectoryEntry>();
    
        foreach (object o in members)
        {
            DirectoryEntry deMember = new DirectoryEntry(o);
    
            r.Add(deMember);
        }
    
        deGroup.Invoke("Add", strUserPath);
        deGroup.CommitChanges();
    
        deGroup.Invoke("Remove", strUserPath);
        deGroup.CommitChanges();
    

    因此,我将代码移到一个ASP.NETWeb应用程序中,该应用程序通过web.config的模拟部分模拟服务帐户。我正在模拟的帐户在任何工作站上都没有管理权限,因此我在构造函数中输入用户名/密码,以便输入计算机,如下所示:

    DirectoryEntry deComputer = new DirectoryEntry("WinNT://" + Computername + ",computer", username, password);
    

    用户名是在每个工作站上具有本地管理权限的域帐户的用户名。如果我查看结果deComputer对象的Username属性,我可以看到Username与我输入的匹配。另外,如果我输入了一个无效的密码,它会抛出一个错误,因此它以某种方式进行身份验证。

    但是,如果我现在尝试从远程工作站添加或删除一个用户,我会得到一个一般的拒绝访问错误。如果我添加ASP.Net在该工作站上作为本地管理员使用的服务帐户,它将添加和删除没有问题。

    所以接下来我尝试使用LogonAPI(advapi32.dll->LogonUser调用)以用户帐户登录,该帐户是所有工作站上的本地管理员,模拟生成的WindowsIdentity并尝试仅运行原始的解压缩程序实例化。当我执行此操作时,每个属性(路径除外)都会返回一个OLE异常。。。

    我很迷茫下一步该怎么办。任何帮助都将不胜感激。

    --变通办法--

    3 回复  |  直到 12 年前
        1
  •  1
  •   Oleg    14 年前

    你试过用吗 AuthenticationTypes.Secure 作为的附加参数 DirectoryEntry 在用户名和密码之后?

    顺便说一下,如果你想连接到远程计算机,你不应该使用 LogonUser . 正确的API是 WNetAddConnection2 (见 http://msdn.microsoft.com/en-us/library/aa385413.aspx )或者 NetUseAdd (见 http://msdn.microsoft.com/en-us/library/aa370645.aspx )

        2
  •  0
  •   Peter    12 年前

    因为这是一个很流行的问题,所以我将答案分离出来,并将代码转换为C#

    这是最后的代码,为我工作。在使用DirectoryEntry之前,首先使用WNetAddConnection2建立连接。

    public static class CredentialSetter
    {
        public static void SetCredentials()
        {
            string Computername = "SomeComputer";
            //Create connection to remote computer'
            using (NetworkConnection nc = new NetworkConnection("\\\\" + Computername + "", new NetworkCredential("Domain\\Login", "Password")))
            {
                //try connecting using DirectoryEntry to the same machine and add me as a user'
                string strUserPath = string.Format("WinNT://{0}/{1},user", "DOMAIN", "USER");
                DirectoryEntry deGroup = new DirectoryEntry("WinNT://" + Computername + "/Administrators");
                deGroup.RefreshCache();
    
                //add and remove the user from the group'
                deGroup.Invoke("Add", strUserPath);
                deGroup.CommitChanges();
                Console.WriteLine("User Added to computer " + Computername);
    
                deGroup.Invoke("Remove", strUserPath);
                deGroup.CommitChanges();
                Console.WriteLine("User Removed from computer " + Computername);
    
                deGroup.Close();
            }
            Console.ReadLine();
        }
    
        public class NetworkConnection : IDisposable
        {
            private string _networkName;
            public NetworkConnection(string networkName, NetworkCredential credentials)
            {
                _networkName = networkName;
    
                dynamic netResource = new NetResource
                {
                    Scope = ResourceScope.GlobalNetwork,
                    ResourceType = ResourceType.Disk,
                    DisplayType = ResourceDisplaytype.Share,
                    RemoteName = networkName
                };
    
                dynamic result = WNetAddConnection2(netResource, credentials.Password, credentials.UserName, 0);
    
                if (result != 0)
                {
                    throw new IOException("Error connecting to remote share", result);
                }
            }
    
            ~NetworkConnection()
            {
                Dispose(false);
            }
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            protected void Dispose(bool disposing)
            {
                WNetCancelConnection2(_networkName, 0, true);
            }
    
            [DllImport("mpr.dll")]
            private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags);
    
            [DllImport("mpr.dll")]
            private static extern int WNetCancelConnection2(string name, int flags, bool force);
        }
    
        [StructLayout(LayoutKind.Sequential)]
        public class NetResource
        {
            public ResourceScope Scope;
            public ResourceType ResourceType;
            public ResourceDisplaytype DisplayType;
            public int Usage;
            public string LocalName;
            public string RemoteName;
            public string Comment;
            public string Provider;
        }
    
        public enum ResourceScope : int
        {
            Connected = 1,
            GlobalNetwork,
            Remembered,
            Recent,
            Context
        }
    
        public enum ResourceType : int
        {
            Any = 0,
            Disk = 1,
            Print = 2,
            Reserved = 8
        }
    
        public enum ResourceDisplaytype : int
        {
            Generic = 0x0,
            Domain = 0x1,
            Server = 0x2,
            Share = 0x3,
            File = 0x4,
            Group = 0x5,
            Network = 0x6,
            Root = 0x7,
            Shareadmin = 0x8,
            Directory = 0x9,
            Tree = 0xa,
            Ndscontainer = 0xb
        }
    }
    
        3
  •  -1
  •   Helvio Junior    10 年前

    错误(0x80004005):未指定的错误

    我在连接到远程窗口时遇到了一些问题,错误为(0x80004005):未指定的错误。我决定如下:

    //Define path
    //This path uses the full path of user authentication
    String path = string.Format("WinNT://{0}/{1},user", server_address, username);
    DirectoryEntry deBase = null;
    try
    {
        //Try to connect with secure connection
        deBase = new DirectoryEntry(path, username, _passwd, AuthenticationTypes.Secure);
    
        //Connection test
        //After test define the deBase with the parent of user (root container)
        object nativeObject = deBase.NativeObject;
        deBase = deBase.Parent;
    
    }
    catch (Exception ex)
    {
        //If an error occurred try without Secure Connection
        try
        {
            deBase = new DirectoryEntry(path, username, _passwd);
    
            //Connection test
            //After test define the deBase with the parent of user (root container)
            object nativeObject = deBase.NativeObject;
            deBase = deBase.Parent;
            nativeObject = deBase.NativeObject;
    
        }
        catch (Exception ex2)
        {
            //If an error occurred throw the error
            throw ex2;
        }
    }
    

    希望有帮助。 小海尔维奥