LDAP - 从 IIS 获取用户的组名失败

Posted

技术标签:

【中文标题】LDAP - 从 IIS 获取用户的组名失败【英文标题】:LDAP - Getting user's group names fails from IIS 【发布时间】:2012-12-11 13:40:11 【问题描述】:

我遵循tutorial 在 ASP.NET/C# 4.0 Web 应用程序上实现 LDAP 身份验证。虽然事情似乎确实有效,但当我将网站置于 IIS7 下时,它无法获取组名。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Collections;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;

namespace KEWeb

    public class LdapAuthentication
    
        private string _path;
        private string _filterAttribute;
        private string _username;
        private string _password;
        private string _domain;
        private string _domainAndUsername;
        private DirectoryEntry _entry;
        private DirectorySearcher _search;
        private SearchResult _result;

        public LdapAuthentication(string path, string domain, string username, string password)
        
            _path = path;
            _domain = domain;
            _username = username;
            _password = password;
            _domainAndUsername = _domain + @"\" + _username;
            _entry = new DirectoryEntry(_path, _domainAndUsername, _password);

        

        public bool IsAuthenticated()
        
            try
            
                Object obj = _entry.NativeObject;
                _search = new DirectorySearcher(_entry);
                _search.Filter = "(SAMAccountName=" + _username + ")";
                _search.PropertiesToLoad.Add("cn");
                _result = _search.FindOne();
                if (null == _result)  return false; 
                _path = _result.Path;
                _filterAttribute = (String)_result.Properties["cn"][0];
            
            catch (Exception ex)  throw new Exception("Error authenticating user: " + ex.Message); 
            return true;
        

        public string GetGroups()
        
            string r = "";
            try
            
                Object obj = _entry.NativeObject;
                _search = new DirectorySearcher(_entry);
                _search.Filter = "(SAMAccountName=" + _username + ")";
                _search.PropertiesToLoad.Add("cn");
                _result = _search.FindOne();
                if (null != _result)
                
                    _path = _result.Path;
                    _filterAttribute = (String)_result.Properties["cn"][0];
                    _search = new DirectorySearcher(_path);
                    _search.Filter = "(cn=" + _filterAttribute + ")";
                    _search.PropertiesToLoad.Add("memberOf");
                    StringBuilder groupNames = new StringBuilder();
                    _result = _search.FindOne();
                    int propertyCount = _result.Properties["memberOf"].Count;
                    String dn;
                    int equalsIndex, commaIndex;
                    for (int propertyCounter = 0; propertyCounter < propertyCount; propertyCounter++)
                    
                        dn = (String)_result.Properties["memberOf"][propertyCounter];
                        equalsIndex = dn.IndexOf("=", 1);
                        commaIndex = dn.IndexOf(",", 1);
                        if (-1 == equalsIndex)  return null; 
                        groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1));
                        groupNames.Append("|");
                    
                    r = groupNames.ToString();
                
            
            catch (Exception ex)  throw new Exception("Error obtaining group names: " + ex.Message); 

            return r;
        
    

在 Visual Studio 2010 的调试中运行它时,它工作正常。但是在 IIS7 上,它给出了一个错误An operations error occured. Not sure how to debug this while under IIS,虽然我确信这是可能的。如果我完全忽略 GetGroups() 并将该代码注释掉,它可以工作,但我当然需要这些组名。

PS - 是的,上面的代码与原始代码完全不同,我对其进行了调整以重新使用一些多余的东西。然而,在我改变它之前,我确实遇到了这个问题。

【问题讨论】:

这是目录权限问题吗?换句话说:连接到 IIS 服务器的用户(或机器)是否有权执行查询?在我的场景中,我的开发框不是目录的成员。我会查询,并在几乎所有查询中获得 DirectoryServicesCOMException。 如果是这种情况,那么情况就会相反,因为正在工作的是标准用户,而 IIS 机器是域管理员,但是 IIS 再次在会话 0 中运行. 两台机器都属于同一个子网中的同一个域。 在我们的环境中,我们必须将应用程序池的身份设置为有权访问目录的用户。 我很确定这是问题所在,只是在更改后,我仍然遇到同样的问题。 【参考方案1】:

您正在为组使用错误的项目 - 您需要使用:

_search = new DirectorySearcher(_path);

GetGroups() 电话中。 _path 变量由IsAuthenticated() 调用设置。

【讨论】:

我不明白你在说什么,你上面的代码行正是我的代码。 等等,它实际上有两次,我明白你现在在说什么,我有两次的原因是它在获取组名时当场重新验证。我遇到了GetGroups() 不起作用的问题,因为从未调用过IsAuthenticated()。也许我只需要重新组织整个班级。 您正在回收真正应该按功能使用的物品,例如DirectorySearcher 对象和 getGroups 调用中的重复搜索确实让我在查看代码时感到困惑。如果您在 getGroups 中的重新身份验证没有重置 _path,那么您使用 _path 进行的搜索最终会尝试使用未经身份验证的 DirectoryEntry 进行搜索,这会触发操作错误 虽然不幸的是这并没有帮助我找到并解决我的问题,但它确实帮助我更好地了解问题的根源。【参考方案2】:

如果您附加到 w3wp 进程,您可以在 iis 下调试应用程序。使用 CTRL+Alt+P 热键附加到它,或转到调试菜单并选择附加到进程...并选中“显示所有会话中的进程”复选框。

【讨论】:

...假设 IIS 和 Visual Studio 在同一台机器上?因为他们不是。 Visual Studio 有一个远程调试器工具。它的默认位置是 C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Remote Debugger。您需要将 msvsmon.exe 复制到 iis 所在的计算机并启动它。然后转到 Studio 并从 Qualifier 浏览到远程计算机。毕竟,您应该看到 w3wp 进程并附加到它。但远程机器必须与运行 Studio 的机器在同一个域中。【参考方案3】:

这可能为时已晚,但我遇到了完全相同的问题。

对我来说,IIS 站点启用了 ASP.Net 模拟和匿名,并且模拟用户被配置为使用经过身份验证的用户。由于还启用了匿名,因此这总是会失败,因为匿名用户无权访问 AD。

将 ASP.Net 模拟更改为使用有效的 AD 帐户,瞧!

约翰

PS。我也和你在同一个教程中工作。 :)

【讨论】:

以上是关于LDAP - 从 IIS 获取用户的组名失败的主要内容,如果未能解决你的问题,请参考以下文章

有没有一种简单的方法可以在 django 中获取用户的组名

如何将所有 memberOf 属性分配给 LDAP 中的特定用户

我想从LDAP中获取所有的用户信息,用ldapTemplate中的search方法 ,请问应该怎么写,过滤器 filter怎么写

为啥我的 LDAP 重定向脚本对一个用户失败?

Hive 中的 Ldap 身份验证用户过滤器:失败

C# LDAP 用户更改密码失败。 SSL连接是必须的吗?