【问题标题】:UserPrincipal extensions returns computersUserPrincipal 扩展返回计算机
【发布时间】:2018-08-30 06:11:52
【问题描述】:

我是 Active Directory 的新手,我目前正在为一个项目开发一个库,以便轻松管理我们的 Active Directory 对象,如用户、资源、组等。

该库位于 .NetStandard 2.0 中,我使用来自

的 Principal 类
System.DirectoryServices.AccountManagement

由于 UserPrincipal 类不包含我们可能需要的所有属性,因此我尝试实现一个 UserPrincipalExtended 类,目前只添加 Initials 属性。

这是我的课:

[DirectoryObjectClass("user")]
[DirectoryRdnPrefix("CN")]
public class UserPrincipalExtended : UserPrincipal
{
    public UserPrincipalExtended(PrincipalContext context) : base(context) { }

    public UserPrincipalExtended(PrincipalContext context, string samAccountName, string password, bool enabled) : base(context, samAccountName, password, enabled) { }

    [DirectoryProperty("Initials")]
    public string Initials
    {
        get
        {
            if (ExtensionGet("initials").Length != 1) return null;

            return (string)ExtensionGet("initials")[0];

        }
        set { ExtensionSet("initials", value); }
    }

    public static new UserPrincipalExtended FindByIdentity(PrincipalContext context, string identityValue)
    {
        return (UserPrincipalExtended)FindByIdentityWithType(context, typeof(UserPrincipalExtended), identityValue);
    }

    public static new UserPrincipalExtended FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
    {
        return (UserPrincipalExtended)FindByIdentityWithType(context, typeof(UserPrincipalExtended), identityType, identityValue);
    }
}

当我使用 UserPrincipal 类在活动目录中进行搜索时,它按预期工作:

using (var context = _contextProvider.GetPrincipalContext())
using (var query = new UserPrincipal(context))
using (var searcher = new PrincipalSearcher(query))
{
    foreach (var principal in searcher.FindAll())
    {
        UserPrincipal userPrincipal = principal as UserPrincipal;

        if (CheckHelper.IsFilled(userPrincipal))
        {
            Console.WriteLine($"{userPrincipal.StructuralObjectClass} : {userPrincipal.SamAccountName}");
        }
    }
}

/*Output
user : cadmin
user : Guest
user : DefaultAccount
*/

但如果我尝试使用我自己的类执行相同的搜索,结果还包含计算机:

using (var context = _contextProvider.GetPrincipalContext())
using (var query = new UserPrincipalExtended(context))
using (var searcher = new PrincipalSearcher(query))
{
    foreach (var principal in searcher.FindAll())
    {
        UserPrincipalExtended userPrincipalExtended = principal as UserPrincipalExtended;

        if (CheckHelper.IsFilled(userPrincipalExtended))
        {
            Console.WriteLine($"userPrincipalExtended.StructuralObjectClass} : {userPrincipalExtended.SamAccountName}");
        }
    }
}
/*Output
user : cadmin
user : Guest
user : DefaultAccount
computer : WS001$
computer : WS002$
computer : WS003$
*/

因为我的 UserPrincipalExtended 类具有属性:

[DirectoryObjectClass("user")]

我认为这足以过滤活动目录中的此对象类型,但似乎没有。

知道这里发生了什么吗?

干杯

【问题讨论】:

  • computer 继承自标准 AD 目录架构中的 user。所有计算机“都是”用户。
  • 但是,当我使用 UserPrinicpal 进行搜索时,为什么没有返回它们?为什么我扩展了这个类之后行为会有所不同?
  • 微软没有发布相关的源代码,referencesource.microsoft.com/#q=system.directoryservices所以你必须使用反编译器来挖掘它。
  • 在您的课堂上,您使用的是UserPrincipalExtended。在活动目录中的示例搜索中,您使用的是UserPrincipal。因此,您并没有像您所说的那样尝试执行相同的搜索

标签: c# .net active-directory ldap userprincipal


【解决方案1】:

在您的构造函数中,您可以将ObjectCategory 属性设置为User

[DirectoryObjectClass("user")]
[DirectoryRdnPrefix("CN")]
public class UserPrincipalExtended : UserPrincipal
{
    public UserPrincipalExtended(PrincipalContext context) : base(context)
    {
        // Set ObjectCategory to user so computer objects are not returned
        ExtensionSet("objectCategory", "user");
    }

    [DirectoryProperty("Initials")]
    public string Initials
    {
        get
        {
            if (ExtensionGet("initials").Length != 1) return null;
            return (string)ExtensionGet("initials")[0];
        }
        set { ExtensionSet("initials", value); }
    }
}

【讨论】:

    【解决方案2】:

    microsoft Principal types filter creating code

    也遇到了这个问题。翻遍了源码,找到了这样的解决方法。

    [DirectoryObjectClass("user)(objectCategory=user")]
    

    【讨论】: