Active Directory UserPrincipal.Current.GetGroups()仅在本地返回组,而不是Web服务器

3
以下内容在我的本地开发环境中表现良好。但是当我将其移动到Web服务器上时,它会失败并且不会记录任何错误:
public static List<string> getAuthorizationGrps(string userName)
    {
        List<string> grps = new List<string>();

        try
        {
            PrincipalSearchResult<Principal> groups = UserPrincipal.Current.GetGroups();
            IEnumerable<string> groupNames = groups.Select(x => x.SamAccountName);
            foreach (var name in groupNames)
            {
                grps.Add(name.ToString());
            }
            return grps;
        }
        catch (Exception ex)
        {
            Log.WriteLog("Error in retriving form data: " + ex.Message);
        }
    }

我需要在Web服务器上设置权限才能查询组吗?我可以轻松地获取当前用户,无论是在本地还是在Web服务器上。

如果您有任何想法,将不胜感激,因为我已经为此奋斗了2天。

2个回答

2
大约6个月前,我们遇到了类似的问题。我们的代码调用了UserPrincipal.Current.GetGroups()并在foreach循环中枚举对象。在测试和生产中都可以正常工作,直到有一天早上,一个同事执行代码时不断出现异常。枚举groupNames对象开始抛出IndexOutOfRangeException异常。经过一个小时的努力,我们无法找出问题所在,因此我添加了一个补救措施,调用了一个存储过程,该存储过程进行了一个类似于here第二个答案的ADSI调用。虽然这不是很美观,但它从未出现过任何问题。

0

我假设这是你的环境

Web browser --> Web Server --> Domain Controller

除非您在同一台机器上运行Web浏览器和Web服务器Web服务器和域控制器,否则您需要设置Kerberos委派才能使上述代码正常工作。我猜您的开发框架之所以能够工作,是因为您在同一台机器上运行了Web浏览器和Web服务器。

您可以轻松地从Google中找到大量教您如何配置IIS和ASP.NET的Kerberos委派的文章。这里是一个例子。我不会在这里详细介绍。重点是您的ASP.NET应用程序正在模拟客户端凭据,并尝试使用该客户端凭据查询Active Directory。如果您没有正确设置委派,Windows将认为您模拟的凭据无法访问网络。在您的情况下,您无法访问域控制器。这是一项安全措施。这只是为了确保服务器不能代表最终用户在网络上执行操作,除非明确授予其执行该操作的权限。

另一种解决方案是更改您的代码。因此,在调用GetGroups之前,您需要撤销模拟,再次成为IIS AppPool帐户。如果您的AppPool帐户配置为域帐户,并且具有足够的权限读取Active Directory,则可以查询用户组的Active Directory。

这里有一个blob讨论了这个问题。这是我认为应该可以在没有任何Kerberos委派设置的情况下工作的代码。不过我没有测试过。

public static List<string> getAuthorizationGrps(string userName)          
{          
    List<string> grps = new List<string>();          

    try          
    {
        var currentUser = UserPrincipal.Current;
        RevertToSelf();             
        PrincipalSearchResult<Principal> groups = currentUser.GetGroups();          
        IEnumerable<string> groupNames = groups.Select(x => x.SamAccountName);          
        foreach (var name in groupNames)          
        {          
            grps.Add(name.ToString());          
        }          
        return grps;          
    }          
    catch (Exception ex)          
    {          
        Log.WriteLog("Error in retriving form data: " + ex.Message);          
    }          
}      

我正在使用.Net 4.0。由于某种原因,您提供的代码无法正常工作。但是,在遵循您的基本步骤后,我将应用程序池更改为在Network Services下运行,现在可以成功完成获取用户的任务。谢谢! - Russell Walters
1
你需要自己声明RevertToSelf。这是一个pinvoke。请查看博客中如何声明它的方法。 - Harvey Kwok

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接