Python-ldap无法成功绑定。

13

我在寻找答案方面并没有任何运气,所以就在这里问了。

当我尝试使用python-ldap连接AD服务器时,它似乎对某些功能成功运行,而对其他功能则不适用。我的连接:

>>>import sys
>>>import ldap

>>>l = ldap.initialize("ldap://company.com:389")
>>>l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
>>>l.simple_bind_s("user@company.com","password")
(97, [], 1, [])

通过一些简单的谷歌搜索,我发现“97”意味着成功,尽管成功的级别有点奇怪。但出于某种原因,我找不到关于状态码“1”的任何信息。如果我在连接上运行一些ldap函数,其中一些会工作,而另一些则不会。

>>>l.whoami_s()
'u:COMPANY.COM\\user'

似乎可以正常返回,但是

>>> base_dn = 'dc=company,dc=com'
>>> retrieveAttributes = ["uniquemember"]
>>> searchFilter = "cn=user"
>>> l.search_s(base_dn, ldap.SCOPE_SUBTREE,searchFilter,retrieveAttributes)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/user/.envs/scoring/local/lib/python2.7/site-packages/ldap/ldapobject.py", line 552, in search_s
    return self.search_ext_s(base,scope,filterstr,attrlist,attrsonly,None,None,timeout=self.timeout)
  File "/home/user/.envs/scoring/local/lib/python2.7/site-packages/ldap/ldapobject.py", line 546, in search_ext_s
    return self.result(msgid,all=1,timeout=timeout)[1]
  File "/home/user/.envs/scoring/local/lib/python2.7/site-packages/ldap/ldapobject.py", line 458, in result
    resp_type, resp_data, resp_msgid = self.result2(msgid,all,timeout)
  File "/home/user/.envs/scoring/local/lib/python2.7/site-packages/ldap/ldapobject.py", line 462, in result2
    resp_type, resp_data, resp_msgid, resp_ctrls = self.result3(msgid,all,timeout)
  File "/home/user/.envs/scoring/local/lib/python2.7/site-packages/ldap/ldapobject.py", line 469, in result3
    resp_ctrl_classes=resp_ctrl_classes
  File "/home/user/.envs/scoring/local/lib/python2.7/site-packages/ldap/ldapobject.py", line 476, in result4
    ldap_result = self._ldap_call(self._l.result4,msgid,all,timeout,add_ctrls,add_intermediates,add_extop)
  File "/home/user/.envs/scoring/local/lib/python2.7/site-packages/ldap/ldapobject.py", line 99, in _ldap_call
    result = func(*args,**kwargs)
OPERATIONS_ERROR: {'info': '000004DC: LdapErr: DSID-0C0906E8, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db1', 'desc': 'Operations error'}

我很困惑为什么whoami命令可以正常运行,但搜索命令却不能。我的用户是域管理员,所以权限应该不是问题。有人能解释一下吗?


1
我在我的Python代码中有这一行访问LDAP的代码,去年我把它放在那里,但我不记得为什么要这样做:l.set_option(ldap.OPT_REFERRALS, 0)。 - Christopher Mahan
在添加了这个之后仍然收到相同的消息,谢谢想法。 - Titus P
看了一下我以前的LDAP代码,发现我在searchFilter参数上使用了不同的语法。按照你的情况进行翻译,应该是searchFilter = "(& (cn=user) )". 也许可以试试看有没有区别? - DMH
4个回答

20

我遇到了和你完全一样的错误,我所做的是添加了这行代码(就像Christopher建议的那样),在进行绑定之前加上l.set_option(ldap.OPT_REFERRALS,0),例如:

conn.protocol_version = ldap.VERSION3
conn.set_option(ldap.OPT_REFERRALS, 0)
conn.simple_bind_s(user, pw)

然后我的LDAP连接就正常工作了。


7

根据@Cas上面所说的,我只需要添加:

connection.set_option(ldap.OPT_REFERRALS,0)

看起来这是一个非常普遍的问题,已经被添加到python-ldap FAQ中:

问:我的脚本绑定到了MS Active Directory,但搜索操作会导致异常ldap.OPERATIONS_ERROR,并显示诊断消息文本"In order to perform this operation a successful bind must be completed on the connection."。这里发生了什么?

答:从域级别搜索时,MS AD会为某些对象返回引用(搜索继续),以向客户端指示在哪里查找这些对象。客户端追踪引用是一个有缺陷的概念,因为LDAPv3没有指定在追踪引用时要使用哪些凭据。Windows客户端应该简单地使用他们的Windows凭据,但当从任意LDAP服务器接收并指向引用时,这通常不起作用。因此,默认情况下,libldap会自动使用匿名访问内部追踪引用,但这在MS AD中失败了。所以最好的方法是关闭这种行为:

l = ldap.initialize('ldap://foobar')

l.set_option(ldap.OPT_REFERRALS,0)


1

尝试:

import ldap

connect = ldap.initialize("ldap://example.com")
connect.set_option(ldap.OPT_REFERRALS, 0)
try:
    connect.simple_bind_s(login, password)
    connect.search_s("dc=example,dc=com",
                     ldap.SCOPE_SUBTREE,
                     'userPrincipalName={}'.format(login),
                     ['cn'])
except (ldap.INVALID_CREDENTIALS, ldap.OPERATIONS_ERROR):
    return False
retrurn True

在这里,我们使用凭据绑定LDAP,如果没有出现错误,我们尝试在LDAP中搜索用户的CN。如果出现空密码且不正确,则会引发OPERATIONS_ERROR,因为没有实际使用凭据进行绑定。

0
如果您在使用flask-simpleldap时遇到此错误,可以使用以下一行代码解决:
app.config['LDAP_CUSTOM_OPTIONS'] = {l.OPT_REFERRALS: 0}

这里有一个例子在这里


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