python 中的 LDAP 查询

发布于 2024-10-14 11:10:43 字数 279 浏览 1 评论 0原文

我想在 ldap 中执行以下查询

ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(uid=w2lame)(objectClass=posixAccount))" gidnumber
ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(gidNumber=1234)(objectClass=posixGroup))" cn

并使用由此获得的变量。我怎样才能做到这一点?

I want to execute the following query in the ldap

ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(uid=w2lame)(objectClass=posixAccount))" gidnumber
ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(gidNumber=1234)(objectClass=posixGroup))" cn

And use the variables thus obtained. How can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

星光不落少年眉 2024-10-21 11:10:43

虽然接受的答案实际上显示了绑定到 LDAP 服务器的正确方法,但我确实觉得它没有全面回答这个问题。这是我最终实现的获取用户的邮件和部门的方法。这在某种程度上混合了原始问题所需的属性。

l = ldap.initialize('ldap://ldap.myserver.com:389')
binddn = "cn=myUserName,ou=GenericID,dc=my,dc=company,dc=com"
pw = "myPassword"
basedn = "ou=UserUnits,dc=my,dc=company,dc=com"
searchFilter = "(&(gidNumber=123456)(objectClass=posixAccount))"
searchAttribute = ["mail","department"]
#this will scope the entire subtree under UserUnits
searchScope = ldap.SCOPE_SUBTREE
#Bind to the server
try:
    l.protocol_version = ldap.VERSION3
    l.simple_bind_s(binddn, pw) 
except ldap.INVALID_CREDENTIALS:
  print "Your username or password is incorrect."
  sys.exit(0)
except ldap.LDAPError, e:
  if type(e.message) == dict and e.message.has_key('desc'):
      print e.message['desc']
  else: 
      print e
  sys.exit(0)
try:    
    ldap_result_id = l.search(basedn, searchScope, searchFilter, searchAttribute)
    result_set = []
    while 1:
        result_type, result_data = l.result(ldap_result_id, 0)
        if (result_data == []):
            break
        else:
            ## if you are expecting multiple results you can append them
            ## otherwise you can just wait until the initial result and break out
            if result_type == ldap.RES_SEARCH_ENTRY:
                result_set.append(result_data)
    print result_set
except ldap.LDAPError, e:
    print e
l.unbind_s()

While the accepted answer does in fact show a proper way to bind to an LDAP server I do feel it didn't answer the question holistically. Here is what I ended up implementing to grab the mail and department of a user. This somewhat blends the required attributes from the original question.

l = ldap.initialize('ldap://ldap.myserver.com:389')
binddn = "cn=myUserName,ou=GenericID,dc=my,dc=company,dc=com"
pw = "myPassword"
basedn = "ou=UserUnits,dc=my,dc=company,dc=com"
searchFilter = "(&(gidNumber=123456)(objectClass=posixAccount))"
searchAttribute = ["mail","department"]
#this will scope the entire subtree under UserUnits
searchScope = ldap.SCOPE_SUBTREE
#Bind to the server
try:
    l.protocol_version = ldap.VERSION3
    l.simple_bind_s(binddn, pw) 
except ldap.INVALID_CREDENTIALS:
  print "Your username or password is incorrect."
  sys.exit(0)
except ldap.LDAPError, e:
  if type(e.message) == dict and e.message.has_key('desc'):
      print e.message['desc']
  else: 
      print e
  sys.exit(0)
try:    
    ldap_result_id = l.search(basedn, searchScope, searchFilter, searchAttribute)
    result_set = []
    while 1:
        result_type, result_data = l.result(ldap_result_id, 0)
        if (result_data == []):
            break
        else:
            ## if you are expecting multiple results you can append them
            ## otherwise you can just wait until the initial result and break out
            if result_type == ldap.RES_SEARCH_ENTRY:
                result_set.append(result_data)
    print result_set
except ldap.LDAPError, e:
    print e
l.unbind_s()
通知家属抬走 2024-10-21 11:10:43

这是 python-ldap 的示例生成器。

ldap_server 是从 ldap.initialize() 获取的对象。您可能还需要在调用此函数之前进行绑定,具体取决于您使用的 LDAP 服务器以及您尝试查询的内容。 base_dnfilter_ 与命令行版本中的类似。 limit 是返回的最大记录数。

def _ldap_list(ldap_server, base_dn, filter_, limit=0):
    """ Generator: get a list of search results from LDAP asynchronously. """

    ldap_attributes = ["*"] # List of attributes that you want to fetch.
    result_id = ldap_server.search(base_dn, ldap.SCOPE_SUBTREE, filter_, ldap_attributes)
    records = 0

    while 1:
        records += 1

        if limit != 0 and records > limit:
            break

        try:
            result_type, result_data = ldap_server.result(result_id, 0)
        except ldap.NO_SUCH_OBJECT:
            raise DirectoryError("Distinguished name (%s) does not exist." % base_dn)

        if result_type == ldap.RES_SEARCH_ENTRY:
            dn = result_data[0][0]
            data = result_data[0][1]
            yield dn, data
        else:
            break

请记住,将用户提供的值插入到 LDAP 查询中是危险的!这是一种注入形式,允许恶意用户更改查询的含义。请参阅: http://www.python-ldap.org/doc/ html/ldap-filter.html

Here's an example generator for python-ldap.

The ldap_server is the object you get from ldap.initialize(). You will probably need to bind before calling this function, too, depending on what LDAP server you are using and what you are trying to query for. The base_dn and filter_ are similar to what you've got in your command line version. The limit is the maximum number of records returned.

def _ldap_list(ldap_server, base_dn, filter_, limit=0):
    """ Generator: get a list of search results from LDAP asynchronously. """

    ldap_attributes = ["*"] # List of attributes that you want to fetch.
    result_id = ldap_server.search(base_dn, ldap.SCOPE_SUBTREE, filter_, ldap_attributes)
    records = 0

    while 1:
        records += 1

        if limit != 0 and records > limit:
            break

        try:
            result_type, result_data = ldap_server.result(result_id, 0)
        except ldap.NO_SUCH_OBJECT:
            raise DirectoryError("Distinguished name (%s) does not exist." % base_dn)

        if result_type == ldap.RES_SEARCH_ENTRY:
            dn = result_data[0][0]
            data = result_data[0][1]
            yield dn, data
        else:
            break

Please keep in mind that interpolating user-provided values into your LDAP query is dangerous! It's a form of injection that allows a malicious user to change the meaning of the query. See: http://www.python-ldap.org/doc/html/ldap-filter.html

粉红×色少女 2024-10-21 11:10:43

今天早上我在浏览 文档时将其拼凑在一起>ldap 模块。它可以满足OP根据自己的喜好更改过滤器和其他设置的要求。

如果您了解上下文的话,ldap 模块的文档会非常好(这就是我花了一段时间的时间)。而且该模块使用起来出奇的简单。我们有一个使用 ldapserach 在 bash 中编写的类似脚本,该脚本至少长 3 或 4 倍,并且阅读起来更复杂。

此代码接受部分搜索字符串(电子邮件、姓名、uid 或其一部分)并以 LDIF 格式返回结果。我们的想法是让它非常简单地用于非常具体的任务,并且如果可能的话,不使用标志,以便我不太熟练的同事可以快速找到相关信息。

请注意,这是为 LDAP 服务器编写的,该服务器运行在无法从内部网络外部访问且通过 2FA 身份验证保护的计算机上。因此,它可以安全地接受匿名查询。但添加用户和密码应该很简单。

   #! /usr/bin/python3
    
    ### usearch
    ### searches in the LDAP database for part of a name, uid or email and returns mail, uid, and full name
    
    import ldap
    import argparse
    import sys
    import ldif
    
    l = ldap.initialize('ldaps://your.fancy.server.url', bytes_mode=False)
    
    basedn = "dc=foo,dc=bar,dc=baz"
    
    
    ## ARGPARSE stuff!!! 
    
    parser=argparse.ArgumentParser(
        description ='searches the LDAP server', 
        usage='usearch PARTIAL_MATCH (email, name, username)',
        formatter_class = argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('istr', help='searches stuffz')
    parser.print_help
    args = parser.parse_args(None if sys.argv[1:] else ['-h'])
   
   str1 = args.istr
    
    
    sfilter = "(|(sn=*{}*)(mail=*{}*)(uid=*{}*))".format(str1,str1,str1)
    attributes = ["mail","uid","cn"]
    scope = ldap.SCOPE_SUBTREE
    
    r = l.search_s(basedn,scope,sfilter,attributes)
    
    ldif_writer=ldif.LDIFWriter(sys.stdout)
    
    for dn, entry in r:
        ldif_writer.unparse(dn,entry)

正如我所看到的,这里是带有 ldap3 模块的版本。 argparse 部分是复制粘贴的。这次输出是“人类可读的”,而不是 LDIF:

#! /usr/bin/python3
## usearch3
## LDAP3 version 

import ldap3
import argparse
import sys

server = ldap3.Server('ldaps://foo.bar.baz')
conn = ldap3.Connection(server)
conn.bind()
basedn = 'dc=foobar,dc=dorq,dc=baz'
attribs = ['mail','uid','cn']

parser=argparse.ArgumentParser(
    description ='searches the LDAP server and returns user, full name and email. Accepts any partial entry', 
    usage='usearch3 PARTIAL_MATCH (email, name, username)',
    formatter_class = argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('istr', help='searches stuffz')
parser.print_help
args = parser.parse_args(None if sys.argv[1:] else ['-h'])

str1 = args.istr

sfilter = "(|(sn=*{}*)(mail=*{}*)(uid=*{}*))".format(str1,str1,str1)

conn.search(basedn,sfilter)
conn.search(basedn,sfilter,attributes = attribs)

leng = len(conn.entries)
for i in range(leng):
   
    user = conn.entries[i].uid
    fullname = conn.entries[i].cn
    email = conn.entries[i].mail
    
    print("user:\t{}\nname:\t{}\nemail:\t{}\n\n".format(user,fullname,email)) 
    

I cobbled this together this morning while skimming through the documentation of the ldap module. It can fulfil the requirements of the OP changing the filter and the other settings to his liking.

The documentation of the ldap module is pretty good if you understand the context (that's what took me a while). And the module is surprinsingly easy to use. We have a similar script written in bash using ldapserach that is at least 3 or 4 times longer and more complex to read.

This code accepts a partial search string (email, name, uid or part of it) and returns the results in LDIF format. The idea is to make it very simple to use for a very specific task and if possible without using flags so that my less skilled co-workers can find the relevant info quickly.

Note that this is written for an LDAP server that runs on a machine that is not accessible from outside our internal network and which is secured with 2FA authentication. It can, thus, safely accept anonymous queries. But adding user and password should be trivial.

   #! /usr/bin/python3
    
    ### usearch
    ### searches in the LDAP database for part of a name, uid or email and returns mail, uid, and full name
    
    import ldap
    import argparse
    import sys
    import ldif
    
    l = ldap.initialize('ldaps://your.fancy.server.url', bytes_mode=False)
    
    basedn = "dc=foo,dc=bar,dc=baz"
    
    
    ## ARGPARSE stuff!!! 
    
    parser=argparse.ArgumentParser(
        description ='searches the LDAP server', 
        usage='usearch PARTIAL_MATCH (email, name, username)',
        formatter_class = argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('istr', help='searches stuffz')
    parser.print_help
    args = parser.parse_args(None if sys.argv[1:] else ['-h'])
   
   str1 = args.istr
    
    
    sfilter = "(|(sn=*{}*)(mail=*{}*)(uid=*{}*))".format(str1,str1,str1)
    attributes = ["mail","uid","cn"]
    scope = ldap.SCOPE_SUBTREE
    
    r = l.search_s(basedn,scope,sfilter,attributes)
    
    ldif_writer=ldif.LDIFWriter(sys.stdout)
    
    for dn, entry in r:
        ldif_writer.unparse(dn,entry)

And as I was at it, here a version with the ldap3 module. The argparse part is copy-pasted. This time the output is "human readable", instead of LDIF:

#! /usr/bin/python3
## usearch3
## LDAP3 version 

import ldap3
import argparse
import sys

server = ldap3.Server('ldaps://foo.bar.baz')
conn = ldap3.Connection(server)
conn.bind()
basedn = 'dc=foobar,dc=dorq,dc=baz'
attribs = ['mail','uid','cn']

parser=argparse.ArgumentParser(
    description ='searches the LDAP server and returns user, full name and email. Accepts any partial entry', 
    usage='usearch3 PARTIAL_MATCH (email, name, username)',
    formatter_class = argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('istr', help='searches stuffz')
parser.print_help
args = parser.parse_args(None if sys.argv[1:] else ['-h'])

str1 = args.istr

sfilter = "(|(sn=*{}*)(mail=*{}*)(uid=*{}*))".format(str1,str1,str1)

conn.search(basedn,sfilter)
conn.search(basedn,sfilter,attributes = attribs)

leng = len(conn.entries)
for i in range(leng):
   
    user = conn.entries[i].uid
    fullname = conn.entries[i].cn
    email = conn.entries[i].mail
    
    print("user:\t{}\nname:\t{}\nemail:\t{}\n\n".format(user,fullname,email)) 
    
感性不性感 2024-10-21 11:10:43

您可以使用命令模块和 getoutput 来解析 ldap 查询的结果:

from commands import getoutput
result = getoutput('ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(uid=w2lame)(objectClass=posixAccount))"')
print result

您必须在系统中安装 ldapsearch 二进制文件。

you can use the commands module, and the getoutput to parse the result of the ldap query:

from commands import getoutput
result = getoutput('ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(uid=w2lame)(objectClass=posixAccount))"')
print result

you have to have ldapsearch binary installed in your system.

廻憶裏菂餘溫 2024-10-21 11:10:43

您可能想使用 ldap 模块。代码看起来像这样:

import ldap
l = ldap.initialize('ldap://ldapserver')
username = "uid=%s,ou=People,dc=mydotcom,dc=com" % username
password = "my password"
try:
    l.protocol_version = ldap.VERSION3
    l.simple_bind_s(username, password)
    valid = True
except Exception, error:
    print error

You probably want to use the ldap module. Code would look something like:

import ldap
l = ldap.initialize('ldap://ldapserver')
username = "uid=%s,ou=People,dc=mydotcom,dc=com" % username
password = "my password"
try:
    l.protocol_version = ldap.VERSION3
    l.simple_bind_s(username, password)
    valid = True
except Exception, error:
    print error
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文