2016-07-05 58 views
1

我有2个结构域,A和B.域A具有基组A包含用户从域B
我的代码:GroupPrincipal.GetMembers和交叉域成员错误

using (var context = new PrincipalContext(ContextType.Domain, DomainName, User, Password)) 
{ 

    using (var groupPrincipal = GroupPrincipal.FindByIdentity(context, IdentityType.SamAccountName, 
                   groupName)) 
    { 
     if (groupPrincipal == null) return null; 
     using (var principalSearchResult = groupPrincipal.GetMembers(true)) 
     { 
      var changedUsersFromGroup = 
       principalSearchResult 
       .Where(member => member is UserPrincipal) 
       .Where(member => IsModifiedUser(member, usnChanged)) 
       .Cast<UserPrincipal>() 
       .Select(adsUser => new AdsUser(adsUser)).Cast<IAdsUser>() 
       .ToArray(); 

      return changedUsersFromGroup; 
     } 
    } 

} 

系统.DirectoryServices.AccountManagement.PrincipalOperationException: 尝试解析跨商店引用时,在主体的SID所指示的域中找不到目标主体 。

但是,如果我从这里

new PrincipalContext(ContextType.Domain, DomainName, User, Password) 

到域B添加用户,它工作正常。
我该如何解决它?

+0

如果您有时间去反编译GAC中的相关程序集,您可能会看到此错误消息的条件是什么条件。我个人的猜测是有一个当时连接问题给DC,所以这个消息是误导性的。除非第二次尝试,否则解决起来很难。 –

回答

0

发现问题并向MS报告为错误。目前不可能做到这一点。净:(但它通过查询原生C++ api工作

0

检查在未投射到UserPrincipal时其行为是否有所不同,例如,

var changedUsersFromGroup = principalSearchResult.ToArray(); 

根据other threads这可能是一些问题。同样根据MSDN,使用GetMembers(true)返回的主集合不包含组对象,只返回叶节点,因此也许根本不需要该投射。接下来,检查这种搜索将返回多少结果。如果您的AD有许多用户/嵌套组,最好尽量不要使用GetMembers(true)以确保它适用于小型用户组。

0

看起来您正在定义域A的PrincipalContext(因此您可以获取组),但由于组中的用户在域B中定义,因此上下文无法访问它们(因为它是域A上下文)。

您可能需要为域B定义第二个'PricipalContext`并针对它运行查询并使用可能位于域A组中的用户的SID列表来过滤对象(您需要获取SID列表,而不会导致底层代码尝试并解决它们)。

希望它有帮助!

0

不幸的是我目前无法测试它,但也许你可以试试这个

var contextB = new PrincipalContext(ContextType.Domain, DomainName_B, User_B, Password_B) 
[..] 
    var changedUsersFromGroup = 
        principalSearchResult 
        .Where(member => member is UserPrincipal) 
        .Where(member => IsModifiedUser(member, usnChanged)) 
        .Select(principal => Principal.FindByIdentity(contextB, principal.SamAccountName)) 
        .Cast<UserPrincipal>() 
        .Select(adsUser => new AdsUser(adsUser)).Cast<IAdsUser>() 
        .ToArray(); 

这可以工作,但只,如果所有的成员都是当然的域B。如果它们在不同的域中混合使用,则可能必须先对其进行过滤并遍历您的域。
或者,您可以使用域帐户运行您的应用程序?然后不要传递用户/密码并将所需的访问权限授予此帐户以避免错误。
说明:域上下文将切换为您检索到的主体(如果您注释掉新的AdsUser/IAdsUser Cast部分,则可以在调试模式下查看此主题)。这是一个,似乎导致例外。尽管这正是我无法测试的部分,但我认为AdsUser的创建会为目标域创建一个新的ldap Bind。这与“原始”证书失败。 AdsUser是ActiveDS还是第三方的一部分?
如果传递证书使用基本身份验证,我没有找到任何提示,但我认为它应该。使用应用程序凭证使用协商和“处理这个”到新的AdsUser(..)应该修复问题。