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 服务器上毫无问题地获取当前用户。

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

4

2 回答 2

1

大约 6 个月前,我们遇到了类似的问题。我们的代码调用 UserPrincipal.Current.GetGroups() 并在 foreach 循环中枚举对象。在测试和生产中工作正常,直到一天早上 1 同事在执行代码时不断出现异常。枚举 groupNames 对象开始引发 IndexOutOfRangeException。一个小时后无法弄清楚出了什么问题,所以我添加了一个 kludge,称为一个进行 ADSI 调用的存储过程,类似于这里的第二个答案。它不漂亮,但它从来没有一个问题。

于 2012-08-08T02:06:42.630 回答
0

我假设这是你的环境

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

除非您在同一台机器上运行Web Browser and Web Serveror ,否则Web Server and Domain Controller您需要设置 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);          
    }          
}      
于 2012-08-08T05:29:32.873 回答