【问题标题】:Get job title using System.DirectoryServices.AccountManagement使用 System.DirectoryServices.AccountManagement 获取职位
【发布时间】:2012-03-02 21:12:28
【问题描述】:

我已成功使用 AccountManagement 代码检索基本 AD 信息,但它只返回关于返回对象的一组非常有限的信息。如何使用 AccountManagement 功能从 AD 获取扩展信息。特别是在我的 AD 实例中似乎被称为职称或头衔。

我知道如何使用旧的 DirectoryServices,但我想知道如何使用新的命名空间。

【问题讨论】:

    标签: c#-4.0 active-directory


    【解决方案1】:

    是的,UserPrincipal 上的默认属性集非常有限 - 但最重要的是:有一个简洁的可扩展性故事!

    您需要定义一个从UserPrincipal 下降的类,然后您可以非常轻松地访问更多属性(如果需要)。

    骨架看起来像这样:

    namespace ADExtended
    {
        [DirectoryRdnPrefix("CN")]
        [DirectoryObjectClass("User")]
        public class UserPrincipalEx : UserPrincipal
        {
            // Inplement the constructor using the base class constructor. 
            public UserPrincipalEx(PrincipalContext context) : base(context)
            { }
    
            // Implement the constructor with initialization parameters.    
            public UserPrincipalEx(PrincipalContext context,
                                 string samAccountName,
                                 string password,
                                 bool enabled) : base(context, samAccountName, password, enabled)
            {} 
    
            UserPrincipalExSearchFilter searchFilter;
    
            new public UserPrincipalExSearchFilter AdvancedSearchFilter
            {
                get
                {
                    if (null == searchFilter)
                        searchFilter = new UserPrincipalExSearchFilter(this);
    
                    return searchFilter;
                }
            }
    
            // Create the "Title" property.    
            [DirectoryProperty("title")]
            public string Title
            {
                get
                {
                    if (ExtensionGet("title").Length != 1)
                        return string.Empty;
    
                    return (string)ExtensionGet("title")[0];
                }
                set { ExtensionSet("title", value); }
            }
    
            // Implement the overloaded search method FindByIdentity.
            public static new UserPrincipalEx FindByIdentity(PrincipalContext context, string identityValue)
            {
                return (UserPrincipalEx)FindByIdentityWithType(context, typeof(UserPrincipalEx), identityValue);
            }
    
            // Implement the overloaded search method FindByIdentity. 
            public static new UserPrincipalEx FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
            {
                return (UserPrincipalEx)FindByIdentityWithType(context, typeof(UserPrincipalEx), identityType, identityValue);
            }
        }
    }
    

    这几乎就是全部了! ExtensionGetExtensionSet 方法允许您“向下”进入底层目录条目并获取您可能感兴趣的所有属性....

    现在,在您的代码中,使用新的 UserPrincipalEx 类而不是 UserPrincipal

    using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
    {
        // Search the directory for the new object. 
        UserPrincipalEx myUser = UserPrincipalEx.FindByIdentity(ctx, "someUserName");
    
        if(myUser != null)
        { 
            // get the title which is now available on your "myUser" object!
            string title = myUser.Title;
        }
    }
    

    在此处阅读有关 System.DirectoryServices.AccountManagement 命名空间及其可扩展性故事的所有信息:

    更新:抱歉 - 这是UserPrincipalExSearchFilter 课程 - 错过了原始帖子中的那个。它只是展示了扩展搜索过滤器的能力,如果需要的话:

    public class UserPrincipalExSearchFilter : AdvancedFilters
    {
        public UserPrincipalExSearchFilter(Principal p) : base(p) { }
    
        public void LogonCount(int value, MatchType mt)
        {
            this.AdvancedFilterSet("LogonCount", value, typeof(int), mt);
        }
    }
    

    【讨论】:

    • 这个类型(UserPrincipalExSearchFilter)从何而来?我需要使用上面的模式创建这种类型吗?我实际上把那几行代码拉出来,它似乎工作得很好(除非我遗漏了什么)。
    • @Jay:对不起——我的错——忘了包括这个。更新了我的回复。
    • @marc_s。感谢您指出可扩展性点(ExtensionGet/Set 保护方法),我想有时看起来离家更近是值得的!!)无论如何,您是否知道使用派生的主体对象所需的安全问题/配置。我已经实现了上面的子类,并得到一个异常读取“UserPrincpalEx 类型的主体对象不能用于查询此商店”。有任何想法吗?谢谢。
    • 对不起。我已经浏览了代码,但不知何故删除了顶部的属性。没有这个装饰 FindByIdentity 会抛出一个摇摆器。谢谢
    • @Force -- 在将DirectoryObjectClass 从“Person”更改为“User”之前,我遇到了同样的错误。 (希望你在一年前就知道了)
    【解决方案2】:

    为了增强上面的内容,我敲了一个扩展方法来调用 ExtensionGet。它使用反射来获取您必须继承的受保护方法。例如,如果您从 Groups.Members 返回 UserPrincipalObjects,您可能需要使用它

    public static class AccountManagmentExtensions
    {
        public static string ExtensionGet(this UserPrincipal up, string key)
        {
            string value = null;
            MethodInfo mi = up.GetType()
                .GetMethod("ExtensionGet", BindingFlags.NonPublic | BindingFlags.Instance);
    
            Func<UserPrincipal, string, object[]> extensionGet = (k,v) => 
                ((object[])mi.Invoke(k, new object[] { v }));
    
            if (extensionGet(up,key).Length > 0)
            {
                value = (string)extensionGet(up, key)[0]; 
            }
    
            return value;
        }
    }
    

    【讨论】:

    • +1 这是非常方便的技巧。我当时想“哦,现在我需要子类化!”您只是绕过了该方法受到保护并设计为通过子类访问的事实。让我想起了我写的关于如何使用 .NET 反射来“破坏”OOP 概念的主题:mazdev.blogspot.ae/2011/05/…
    • key的值是什么,不是字符串值。就像 System._comObjectaccountExpires 属性中一样。
    【解决方案3】:

    有更简单的方法可以获取该信息。这是我在 VB.NET 中获得职位的方法:

    Dim yourDomain As New PrincipalContext(ContextType.Domain, "yourcompany.local")
    Dim user1 As UserPrincipal = UserPrincipal.FindByIdentity(yourDomain, principal.Identity.Name)
    Dim Entry As DirectoryServices.DirectoryEntry = user1.GetUnderlyingObject()
    
    Dim JobTitle As String = Entry.Properties.Item("Title").Value.ToString
    

    【讨论】:

    • 有效。 System.DirectoryServices 必须被引用。 C#方式:(ldapEntry.GetUnderlyingObject() as DirectoryEntry)?.Properties["Title"].Value ?? "EMPTY"
    【解决方案4】:

    要扩展 Programmierus 的评论,这里有一个在 C# 中即时执行此操作的简单方法。

        public static string GetProperty(UserPrincipal userPrincipal, string property)
        {
            DirectoryEntry d = (DirectoryEntry)userPrincipal.GetUnderlyingObject();
            return d.Properties[property]?.Value?.ToString();
        }
    

    【讨论】:

      猜你喜欢
      • 2022-11-04
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 2018-11-23
      • 1970-01-01
      • 2021-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多