System.DirectoryServices.AccountManagement.NoMatchingPrincipalException:枚举组时发生错误。找不到这个小组

时间:2016-09-16 06:56:19

标签: c# asp.net-mvc-5 active-directory

我想要由用户主体从Active Directory获取用户组。为此,我编写了以下静态函数:

internal static List<ADGroup> GetGroupsByIdentity(UserPrincipal pUserPrincipal)
{
    var lResult = new List<ADGroup>();

    if (pUserPrincipal != null)
    {
        PrincipalSearchResult<Principal> lGroups = pUserPrincipal.GetAuthorizationGroups();

        // iterate over all groups
        foreach (Principal p in lGroups)
        {
            // make sure to add only group principals
            if (p is GroupPrincipal)
            {
                var lGroupName = "";
                var lGroupSid = "";

                try
                {
                    lGroupName = p.Name;
                    lGroupSid = p.Sid.Value;

                    if (!string.IsNullOrEmpty(lGroupName) && !string.IsNullOrEmpty(lGroupSid) &&
                        !lResult.Any(x => x.Sid == lGroupSid))
                    {
                        lResult.Add(new ADGroup(p));
                    }
                }
                catch (Exception e)
                {
                    if (e is PrincipalOperationException || e is NoMatchingPrincipalException)
                    {
                        // perhaps the SID could not be resolved
                        // perhaps the SID does not exist in the AD any more
                        // ignore and proceed with next

                        p.Dispose();
                        continue;
                    }
                    else
                    {
                        throw;
                    }                           
                }
                finally
                {
                    p.Dispose();
                }
            }

            p.Dispose();
        }
    }

    return lResult;
}

当用户执行此代码时,他会收到异常。这是堆栈的一部分:

System.DirectoryServices.AccountManagement.NoMatchingPrincipalException: 
An error occurred while enumerating the groups. The group could not be found. 
at System.DirectoryServices.AccountManagement.AuthZSet.get_CurrentAsPrincipal() 
at System.DirectoryServices.AccountManagement.FindResultEnumerator`1.get_Current() 
at xxx.xxxxxxxxx.Mvc.CustomSetup.ADHandler.GetGroupsByIdentity(UserPrincipal pUserPrincipal) // the function above
at ...

问题在哪里,我该如何解决?

1 个答案:

答案 0 :(得分:6)

似乎GetAuthorizationGroups()方法有一些限制。这是一个自2009年以来一直存在的旧例外。而且微软不会修复它,因为&#34;有一个合理的解决方法&#34;。 https://connect.microsoft.com/VisualStudio/feedback/details/522539/clr-forum-error-calling-principal-getauthorizationgroups-in-winxp-sp3

使用Principal.IsMemberOf()时出现此错误。我搜索了用户是否存在于自定义组列表中。如果域中没有一个组,则抛出此

System.DirectryServices.AccountManagement.NoMatchingPrincipalException

https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.nomatchingprincipalexception(v=vs.110).aspx

错误示例1使用.IsMemberOf()

List<string> groups = Constants.ADGroups(); // List of AD groups to test against               

var context = new PrincipalContext(
    ContextType.Domain,
    "Domain");

var userPrincipal = UserPrincipal.FindByIdentity(
    context,
    IdentityType.SamAccountName,
    httpContext.User.Identity.Name);

// Verify that the user is in the given AD group (if any)
foreach (var group in groups)
    if (userPrincipal.IsMemberOf(context, IdentityType.Name, group))
        return true;

错误示例2使用.GetAuthorizationGroups():

var context = new PrincipalContext(ContextType.Domain,"Domain");

var userPrincipal = UserPrincipal.FindByIdentity(
                                   context,
                                   IdentityType.SamAccountName,
                                   httpContext.User.Identity.Name);

if (userPrincipal != null)
{
    var principalGroups = userPrincipal.GetAuthorizationGroups();
    foreach (var principalGroup in principalGroups)
    {
        foreach (var group in groups)
        {
            if (String.Equals(
                principalGroup.Name,
                group,
                StringComparison.CurrentCultureIgnoreCase))
            {
                return true;
            }
        }
    }
}

解决方案1:建议的解决方法是迭代AD群组:

GetAuthorizationGroups() is throwing exception

PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups();
var iterGroup = groups.GetEnumerator();
using (iterGroup)
{
    while (iterGroup.MoveNext())
    {
        try
        {
            Principal p = iterGroup.Current;
            Console.WriteLine(p.Name);
        }
        catch (NoMatchingPrincipalException pex)
        {
            continue;
        }
    }
}

解决方案2:我最终使用的是(使用Windows身份验证的MVC应用程序):

这是一种更轻松的方式来检查身份验证,迭代一家大公司的AD可能会很慢......

var wi = HttpContext.Current.User.Identity as WindowsIdentity;
if (wi != null)
{
    var wp = new WindowsPrincipal(wi);
    List<string> groups = Constants.ADGroups(); // List of AD groups to test against

    foreach (var @group in groups)
    {
        Debug.WriteLine($"Searching for {@group}");
        if (wp.IsInRole(@group))
        {
            return true;
        }
    }
}