UserPrincipals.GetAuthorizationGroups枚举组时发生错误(1301).升级到Server 2012域控制器后

Pyn*_*ynt 27 c# active-directory domaincontroller windows-server-2012

研究:

与解决方法类似的问题,但不是对现有问题的实际解决方案

类似的问题指向Microsoft End Point更新为罪魁祸首

上面的链接最适合我的问题,我也在创建这篇文章时查看了Stack Overflow列出的每个类似问题,只有上面引用的问题符合我的问题.

背景:

我一直在使用UserPrincipal.GetAuthorizationGroupsC#.NET 4.0 Web表单站点上Server 2008 R2上运行IIS 7.5的特定页面访问权限2年半.2013年5月15日,我们删除了运行Server 2008(而不是r2)的主域控制器,并将其替换为Server 2012域控制器.第二天,我们开始收到下面列出的例外情况.

我使用Principal Context进行表单身份验证.用户名/通过握手成功并且正确设置了auth cookie,但是后续的Principal Context调用也会UserPrincipal.GetAuthorizationGroups间歇性地调用失败.我们已经解决了Server 2012域控制器中出现的一些BPA问题,但这还没有解决问题.我还建立了一个在两个独立服务器上运行的cron.虽然它们运行相同的代码库,但两个服务器将在不同的时间以组SID解析失败.(开发环境和生产环境).

该问题在Web服务器重启时暂时解决,并且在开发服务器上它将在12小时不能运行后自行解决.生产服务器通常会停止正常运行,直到重新启动而不解决自身.

此时,我正在尝试优化针对网络中特定域控制器的cron以及新DC,并使用当前未能产生更多目标异常时间的标准LDAP查询.到目前为止,我们已经在一台Web服务器上发现它失败的日子没有模式,但它将在大约12小时内恢复.最新结果显示,在上午8点至晚上8点之间,集团SID解决方案失败,然后恢复,几天后它将在晚上8点失败并在早上8点恢复,然后再运行12小时并再次失败.我们希望看看它是否只是一个特定的服务器通信问题,或者看它是否是整个域控制器集.

例外:

Exception information: 
Exception type: PrincipalOperationException 
Exception message: An error (1301) occurred while enumerating the groups.  
The group's SID could not be resolved.
at System.DirectoryServices.AccountManagement.SidList.TranslateSids(String target, IntPtr[] pSids)
at System.DirectoryServices.AccountManagement.SidList..ctor(SID_AND_ATTR[] sidAndAttr)
at System.DirectoryServices.AccountManagement.AuthZSet..ctor(Byte[] userSid, NetCred credentials, ContextOptions contextOptions, String flatUserAuthority, StoreCtx userStoreCtx, Object userCtxBase)
at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOfAZ(Principal p)
at System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroups()
Run Code Online (Sandbox Code Playgroud)

题:

鉴于以上信息,有没有人知道为什么退出Windows Server 2008(而不是r2)并实施新的Server 2012 DC会导致UserPrincipal.GetAuthorizationGroups1301 SID分辨率错误失败?关于消除可能原因的想法也将受到赞赏.

免责声明:

这是我在Stack Overflow上的第一篇文章,我经常在这里研究,但直到现在才加入讨论.请原谅我,如果我应该在其他地方发布,并在发布前随时指出更好的步骤.

更新2013年6月13日:

6月12日,我解决了未处理问题的可能性.时间框架太短,无法确定调整后的代码是否已解决问题,但我会继续更新,因为我们正努力达成一项解决方案,以便在这里有人可以帮忙.

原始代码

    public bool isGroupMember(string userName, ArrayList groupList)
    {
        bool valid = false;

            PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain_server + ".domain.org:636", null, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);

            // find the user in the identity store
            UserPrincipal user =
                UserPrincipal.FindByIdentity(
                    ctx,
                    userName);

            // get the groups for the user principal and
            // store the results in a PrincipalSearchResult object
            PrincipalSearchResult<Principal> groups =
                user.GetAuthorizationGroups();

            // display the names of the groups to which the
            // user belongs
            foreach (Principal group in groups)
            {
                foreach (string groupName in groupList)
                {
                    if (group.ToString() == groupName)
                    {
                        valid = true;
                    }
                }

            }
        return valid;
    }
Run Code Online (Sandbox Code Playgroud)

更新的代码

        public bool isGroupMember(string userName, ArrayList groupList, string domain_server)
        {
        bool valid = false;

            try
            {

                using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain_server + ".domain.org:636", null, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer))
                {

                    // find the user in the identity store
                    UserPrincipal user =
                        UserPrincipal.FindByIdentity(
                            ctx,
                            userName);

                    try
                    {
                        // get the groups for the user principal and
                        // store the results in a PrincipalSearchResult object
                        using (PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups())
                        {
                            // display the names of the groups to which the
                            // user belongs

                            foreach (Principal group in groups)
                            {
                                foreach (string groupName in groupList)
                                {

                                    if (group.ToString() == groupName)
                                    {
                                        valid = true;
                                    }
                                }

                                group.Dispose();

                            }
                        }//end using-2
                    }
                    catch
                    {
                        log_gen("arbitrary info");
                        return false;
                    }
                }//end using-1
            }
            catch
            {
                log_gen("arbitrary info");
                return false;
            }

        return valid;

    }
Run Code Online (Sandbox Code Playgroud)

小智 18

我刚遇到同样的问题,我设法追踪的信息可能会有所帮助; 如上所述,我们已经看到了域控制器运行Server 2012的问题 - 首先是客户部署,然后在我们自己的网络上复制.

经过一些实验,我们发现我们的代码在Server 2012上运行正常,但在客户端系统运行Server 2008时遇到了1301错误代码.关于发生了什么的关键信息在这里找到:

MS博客翻译自德语

下面的链接中提到的修补程序修复了我们的测试系统上的问题

SID S-1-18-1和SID S-1-18-2无法映射

希望这对某人有帮助!正如许多人已经注意到这种方法调用似乎相当脆弱,我们可能会在遇到其他问题之前考虑实施一些替代方法.

加里


Ali*_*vin 5

这是我的解决方案.它似乎一直很好.因为在迭代集合时会出现问题,所以我在迭代时使用不同的方法来处理异常而不阻塞实际的迭代:

private string[] GetUserRoles(string Username)
{    
    List<string> roles = new List<string>();
    try
    {
        string domain = Username.Contains("\\") ? Username.Substring(0, Username.IndexOf("\\")) : string.Empty;
        string username = Username.Contains("\\") ? Username.Substring(Username.LastIndexOf("\\") + 1) : Username;
        if (!string.IsNullOrEmpty(domain) && !string.IsNullOrEmpty(username))
        {
            PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domain);
            UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, username);
            if (user != null)
            {
                PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups();
                int count = groups.Count();
                for (int i = 0; i < count; i++)
                {
                    IEnumerable<Principal> principalCollection = groups.Skip(i).Take(1);
                    Principal principal = null;
                    try
                    {
                        principal = principalCollection.FirstOrDefault();
                    }
                    catch (Exception e)
                    {
                        //Error handling...
                        //Known exception - sometimes AD can't query a particular group, requires server hotfix?
                        //http://support.microsoft.com/kb/2830145
                    }

                    if (principal!=null && principal is GroupPrincipal)
                    {
                        GroupPrincipal groupPrincipal = (GroupPrincipal)principal;
                        if (groupPrincipal != null && !string.IsNullOrEmpty(groupPrincipal.Name))
                        {
                            roles.Add(groupPrincipal.Name.Trim());
                        }
                    }
                }
            }
        }
    }
    catch (Exception e)
    {
        //Error handling...
    }
    return roles.ToArray();
}
Run Code Online (Sandbox Code Playgroud)