活动目录UserPrincipal.Current.GetGroups()返回本地而非Web服务器上的组

以下在我的本地开发框中非常有用。 但是,当我将其移动到Web服务器时,它会失败,甚至不会记录错误:

public static List getAuthorizationGrps(string userName) { List grps = new List(); try { PrincipalSearchResult groups = UserPrincipal.Current.GetGroups(); IEnumerable 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天。

我认为这是你的环境

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

除非您在同一台计算机上运行Web Browser and Web ServerWeb 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 getAuthorizationGrps(string userName) { List grps = new List(); try { var currentUser = UserPrincipal.Current; RevertToSelf(); PrincipalSearchResult groups = currentUser.GetGroups(); IEnumerable 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); } } 

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