为什么 Principal.IsMemberOf() 对某些组返回误报
本文关键字:返回 Principal IsMemberOf 为什么 | 更新日期: 2023-09-27 18:30:55
为什么Principal.IsMemberOf(GroupPrincipal)
(MSDN) 在下面的测试中返回Domain Computers
组的误报?
[TestMethod]
public void DomainComputerTest()
{
var distinguishedName = "CN=MyMachine,DC=SomeDomain,DC=local";
using( var pc = new PrincipalContext( ContextType.Domain, "SomeDomain.local", "UserName", "Password" ) )
using( var computer = ComputerPrincipal.FindByIdentity( pc, IdentityType.DistinguishedName, distinguishedName ) )
{
Assert.IsNotNull( computer );
// Get the groups for the computer.
var groups = computer.GetGroups().Cast<GroupPrincipal>();
foreach( var group in groups )
{
// Immediately turn around and test that the computer is a member of the groups it returned.
Assert.IsTrue( computer.IsMemberOf( group ), "Computer is not member of group {0}", group.Name );
}
}
}
结果消息:断言.IsTrue 失败。计算机不是"域计算机"组的成员
计算机确实是"域计算机"组的成员,"GetGroups()"方法正确返回了该组。实际上,如果尝试将计算机添加到组中,则会引发 PrincipalExistsException。
我可以重现与用户和"域用户"组完全相同的行为。这是因为组是主体组吗?是因为这些是"默认"组吗?
编辑以添加:我们使用的是 .NET 4.5.1。
这似乎是一个一直存在的问题。
我发现的同一个问题的每一个问题都没有答案。我找不到任何说这是作为错误提交的,但似乎自 .NET 3.5 以来就存在了。
我试图让你的例子返回true
(当然,将信息更改为我的工作领域)。无论如何,它都返回了false
.在dotPeek中反编译Principal
类只产生了猜测。在完成并设置Visual Studio以允许单步进入.NET框架代码之后,这是一个失败,因为它不会步入必要的方法。我可以单步执行其他 .NET 框架代码,但Principal
上没有任何内容。不确定这是否与标记为SecurityCriticalAttribute
的方法有关。希望确认这一点。
我给你的建议是将其作为一个错误提交,同时采取不同的路线来确定计算机是否是成员。在我的测试中,group.Members
确实包含计算机。
我在运行 .NET 3.5、4.0、4.5、4.5.1 时遇到了同样的问题
以下是一些参考资料:
解决方法 -- GroupPrincipal.IsMemberOf 总是返回 false
2010 MSDN 博客条目,其中包含与您具有相同问题的注释。
注意:我通常不会这样回答,但是因为我发现这个问题的每个问题都有0个答案或解决方法,我认为未来的读者实际看到关于这个问题的某种"答案"将是有益的。
对于其他发现这一点的开发人员,这是我最终所做的。这是我部署的代码的简化版本,但总而言之,我假设问题是主要组关系。这可能不正确,但它现在对我们有用。
您可以获取此类ComputerPrincipal
的DirectoryEntry
实例。
var entry = (DirectoryEntry)computerPrincipal.GetUnderlyingObject();
我正在使用这种扩展方法来检查主要组关系。
public static bool IsPrimaryGroupFor( this GroupPrincipal group, DirectoryEntry target )
{
// .Value will return an int like "123", which is the last part of the group's SID
var id = target.Properties[ "primaryGroupID" ].Value.ToString();
// strip the account domain SID from the group SID.
var groupId = group.Sid.Value.Remove( 0, group.Sid.AccountDomainSid.Value.Length + 1 );
// If the
return id.Equals( groupId, StringComparison.OrdinalIgnoreCase );
}
我们正在同步 AD 组成员身份,因此我们在类似于以下内容的代码中发现了此问题;
public void AddComputerToGroups( ComputerPrincipal computer, ICollection<GroupPrincipal> groups )
{
var directoryEntry = (DirectoryEntry)computer.GetUnderlyingObject();
foreach( var principal in groups.Where(g=> !computer.IsMemberOf(g) )
{
principal.Members.Add( computer );
principal.Save(); // Exception thrown because computer already existed in the primary group.
}
}
如果您要测试的组成员过多,也会发生这种情况。IsMemberOf 似乎只检查前 1000 个左右的条目。要绕过这种情况,请检查是否分组。成员包含用户/计算机。
因此,我相信您可能会遇到与我在这里相同的问题,但针对的是计算机帐户而不是用户帐户。
Principal.IsInRole("AD 组名称") 始终返回 false,不引发异常
验证执行代码的帐户是否对导致错误/遇到问题的计算机注册到的域中的Computers
和Users
容器具有读取权限。