如何在C#中获取Active Directory用户的所有属性

3

我已经寻找了相当长的时间,希望使用C#代码查询Active Directory用户的所有属性,无论它们是否具有NULL值。这些属性可以通过域服务器上ADSI Edit中用户的属性的属性编辑器选项卡中查看。

ADSI编辑器中的AD用户属性

我需要动态检索这些属性,这意味着我可能无法通过MSDN上的ADSI文档可靠地获得这些属性名称,并且因为并非所有这些属性都可能是用户对象特定的:

https://msdn.microsoft.com/en-us/library/ms675090(v=vs.85).aspx

以下是我迄今为止尝试过的内容,但只获得了用户对象的一小部分属性:

  1. PS command Get-ADUser -Identity administrator -Properties: This retrieved a good part of the attributes, but not nearly all of them and I do not know what .NET Classes and methods are invoked during this command, since TypeName = Microsoft.ActiveDirectory.Management.ADUser, which does not exist in the .NET framework. How can I see the specific methods that are using from .NET in PS?

  2. C# calling this method:

    public bool GetUserAttributes(out List<string> userAttributes, string userName)
    {
        userAttributes = new List<string>();
        var valueReturn = false;
    
        try
        {
            const string pathNameDomain = "LDAP://test.local";
    
            var directoryEntry = new DirectoryEntry(pathNameDomain);
    
            var directorySearcher = new DirectorySearcher(directoryEntry)
            {
                Filter = "(&(objectClass=user)(sAMAccountName=" + userName + "))"
            };
    
            var searchResults = directorySearcher.FindAll();
    
            valueReturn = searchResults.Count > 0;
    
            StreamWriter writer = new StreamWriter("C:\\LDAPGETUSERADEXAMPLE.txt");
    
            foreach (SearchResult searchResult in searchResults)
            {
                foreach (var valueCollection in searchResult.Properties.PropertyNames)
                {
                    userAttributes.Add(valueCollection.ToString() + " = " + searchResult.Properties[valueCollection.ToString()][0].ToString());
    
                    try
                    {
                        writer.WriteLine("Bruger attribut:" + valueCollection);
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
            }
    
  3. C# calling this method:

    public List<string> GetADUserAttributes()
    {
        string objectDn = "CN=testuser,OU=TEST,DC=test,DC=local";
    
        DirectoryEntry objRootDSE = new DirectoryEntry("LDAP://" + objectDn);
        List<string> attributes = new List<string>();
    
        foreach (string attribute in objRootDSE.Properties.PropertyNames)
        {
            attributes.Add(attribute);
        }
    
        return attributes;
    }
    
我该怎么做才能不过滤掉我正在尝试检索的用户对象的任何属性?
我知道默认情况下,Active Directory只显示默认属性或具有值的属性,我正在尝试克服这个限制。
编辑1:
我暂时搁置了具体问题。我一直在尝试基准测试以下哪种方法最快地检索(读取操作)10,000个名为“testuser”的单个AD用户的SAM帐户名,我进行基准测试的方法如下:
1.完成时间:约500毫秒:ADSI-system.directoryservices 2.完成时间:约2700毫秒:Principal-searcher system.directoryservices.accountmanagement 3.完成时间:约无法工作:LDAP-System.DirectoryServices.Protocols 4.完成时间:约60毫秒:SQL-System.Data.SqlClient
我正在从Windows 10机器的工作站查询用户信息,该工作站位于我正在查询的域中。工作站(4个vcpu),DC(2个vpu)和DB(2个vcpu)服务器作为Hyper V vm运行。

我正在努力克服这个限制。这不是一个限制。你想要实现什么目标,也就是为什么你认为你需要这个? - Ansgar Wiechers
@AnsgarWiechers:我需要获取属性名称,比如一个AD用户对象,是因为我想为我的项目创建一个几乎相同的AD缓存。我的想法是在数据库中为每个属性名称创建一个“Users”表格中的列。然后,我的前端网站可以从数据库中检索这些缓存条目及其内容,而不是直接从AD中获取,这样会更快,因为它只需要进行快速的SQL查询,而不是LDAP查询。希望这能澄清问题,否则请提出评论。 - Caspi
你的LDAP查询速度太慢了吗?你对它们进行了基准测试吗?如何测试的?你尝试过使用缓存LDAP代理吗? - Ansgar Wiechers
准确地说,我目前并没有使用LDAP查询,而是通过system.directoryservices类来使用ADSI,而不是特定的LDAP。然而,我曾考虑过仅通过system.directoryservices.protocols.LDAP使用LDAP查询。目前我还没有对LDAP和SQL哪个更快进行基准测试。也许如果我发现LDAP/ADSI与SQL的速度差不多,我会让我的前端直接检索AD信息,这将有优势,因为我不必同步AD和我的缓存AD数据库。我很快就会尝试创建一个基准测试。我将研究LDAP代理缓存。 - Caspi
1个回答

5

任何类可以拥有的所有属性都定义在Active Directory模式中。

使用此链接查询用户类,然后调用GetAllProperties方法即可。

var context = new DirectoryContext(DirectoryContextType.Forest, "amber.local");

using (var schema = System.DirectoryServices.ActiveDirectory.ActiveDirectorySchema.GetSchema(context))
{
    var userClass = schema.FindClass("user");

    foreach (ActiveDirectorySchemaProperty property in userClass.GetAllProperties())
    {
        // property.Name is what you're looking for
    }
}

然而,AD架构可能因一个AD环境而异。例如,第三方程序或Exchange Server可以使用自定义属性扩展架构。这意味着预定义列的解决方案仅适用于特定环境。

1
强烈反对仅包含链接的答案或主要是链接的答案。请考虑引用来源,但将相关解决方案复制到您的答案中。 - David L
@Dimitry:谢谢,看起来正是我想要的。我会测试这个解决方案,并告诉你它是否有效 :) 关于模式仅限于特定环境的问题,我正在尝试通过在安装过程中动态创建数据库列来解决此问题,而不是使用固定的列。这就是为什么我不能依赖文档中的属性满足我的需求的原因。我意识到如果模式发生变化,我需要注意对数据库结构进行扩展。然而,数据库的目的只是作为前端网站的缓存,只用于读取。 - Caspi
@Dimitry:我已经考虑过这个挑战,但不知道如何观察AD更改,但检查USN当然是所需的。你能提供几个提到的方法的参考吗?我计划通过观察USN号码并将更改写入我的数据库来进行实时复制,但我还不知道会产生多少开销以确保非常快速的复制,但我相信域控制器可以处理这个问题,因为它们一直在彼此复制... - Caspi
@DmitryAlexandrov:你能提供任何导致应用程序挂起的ADSI示例代码吗?这样我就可以自己测试了。 我正在尝试对获取AD用户数据的不同方法进行基准测试。目前,我正在努力获取通过System.DirectoryServices.Protocols SendRequestst()方法检索到的用户对象“testuser”的属性。似乎现在已经检索到了用户对象的属性,因为对任何属性的查询(如“cn”)都会导致NULLReferenceexception,即使没有过滤属性... - Caspi
根据性能:System.DirectoryServices.AccountManagement类使用ADSI。 ADSI类在幕后调用LDAP函数。因此,在性能方面,链将是LDAP-> ADSI-> AccountManagement,其中LDAP类是链中最快的。但是,如果您要使用SQL,则SQL更新查询将比任何Active Directory查询慢10倍或更多(我的项目正在执行相同的操作-它将MS SQL数据库与当前AD状态同步)。查看ADUC \ ADSIEdit工具。它们会即时查询LDAP。如果性能适合您,请执行相同的操作。 - oldovets
显示剩余23条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接