如何在ldaptor中使用startTLS?

4 投票
2 回答
1335 浏览
提问于 2025-04-16 21:09

我正在尝试使用ldaptor通过startTLS连接到一个LDAP服务器。在网上搜索并自己尝试后,我找到了这段代码:

from ldaptor.protocols.ldap import ldapclient, ldapsyntax, ldapconnector, distinguishedname
[...]
def main(base, serviceLocationOverrides):
    c=ldapconnector.LDAPClientCreator(reactor, ldapclient.LDAPClient)
    d = c.connect(base, serviceLocationOverrides)
    d.addCallbacks(lambda proto: proto.startTLS(), error)
    [...]
    d.addErrback(error)
    d.addBoth(lambda dummy: reactor.stop())
    reactor.run()

但是这段代码运行时出现了一个AssertionError(断言错误):

[Failure instance: Traceback: <type 'exceptions.AssertionError'>: 
/usr/lib/python2.7/dist-packages/twisted/internet/base.py:1167:mainLoop
/usr/lib/python2.7/dist-packages/twisted/internet/base.py:789:runUntilCurrent
/usr/lib/python2.7/dist-packages/twisted/internet/defer.py:361:callback
/usr/lib/python2.7/dist-packages/twisted/internet/defer.py:455:_startRunCallbacks
--- <exception caught here> ---
/usr/lib/python2.7/dist-packages/twisted/internet/defer.py:542:_runCallbacks
/usr/lib/pymodules/python2.7/ldaptor/protocols/ldap/ldapclient.py:239:_startTLS
/usr/lib/pymodules/python2.7/ldaptor/protocols/pureldap.py:1278:__init__
/usr/lib/pymodules/python2.7/ldaptor/protocols/pureldap.py:1144:__init__
]

我试着在ldaptor的代码里找出导致这个错误的断言,但看起来一切正常。有没有人成功使用ldaptorClient的startTLS?能分享一段代码吗?

非常感谢

再见

2 个回答

2

我使用的是ldaptor 0.0.54,来自这个链接:https://github.com/twisted/ldaptor,在使用StartTLS的时候没有遇到任何问题。

下面是代码:

#! /usr/bin/env python


from twisted.internet import reactor, defer
from ldaptor.protocols.ldap import ldapclient, ldapsyntax, ldapconnector

@defer.inlineCallbacks
def example():
    serverip = 'your.server.name.or.ip'
    basedn = 'o=Organization'
    binddn = 'cn=admin,o=Organization'
    bindpw = 'Sekret'
    query = '(uid=jetsong)'
    c = ldapconnector.LDAPClientCreator(reactor, ldapclient.LDAPClient)
    overrides = {basedn: (serverip, 389)}
    client = yield c.connect(basedn, overrides=overrides)
    client = yield client.startTLS()
    yield client.bind(binddn, bindpw)
    o = ldapsyntax.LDAPEntry(client, basedn)
    results = yield o.search(filterText=query)
    for entry in results:
        print entry

if __name__ == '__main__':
    df = example()
    df.addErrback(lambda err: err.printTraceback())
    df.addCallback(lambda _: reactor.stop())
    reactor.run()
2

我很确定你遇到的问题是我之前也碰到过的。在ldaptor/protocols/pureldap.py的第1144行,有个地方要求LDAPExtendedRequest的requestValue必须是字符串。但根据RFC 2251的规定,这个值是可选的,而且在startTLS请求中特别不应该出现。

所以你的做法是对的;这其实是ldaptor里的一个大bug。根据我了解,作者只测试过在没有TLS的情况下使用简单绑定。你需要把pureldap.py中的那一行注释掉。如果你打算让用户下载或轻松安装ldaptor,那么你需要在自己的代码里创建一个修复过的LDAPExtendedRequest类,并在运行时替换掉它。

我在维护一个使用ldaptor的项目多年后,强烈建议你如果有可能的话,换成python-ldap。因为它封装了OpenLDAP库,虽然构建起来可能会更复杂,特别是要完全支持SSL/SASL。但这样做是值得的,因为ldaptor的问题远不止你遇到的那个。

撰写回答