Python 3 有 LDAP 模块吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1982442/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 23:29:11  来源:igfitidea点击:

Does Python 3 have LDAP module?

pythonldappython-3.x

提问by Calmar

I am porting some Java code to Python and we would like to use Python 3 but I can't find LDAP module for Python 3 in Windows.

我正在将一些 Java 代码移植到 Python,我们想使用 Python 3,但我在 Windows 中找不到 Python 3 的 LDAP 模块。

This is forcing us to use 2.6 version and it is bothersome as rest of the code is already in 3.0 format.

这迫使我们使用 2.6 版本,这很麻烦,因为其余代码已经是 3.0 格式。

采纳答案by ChristopheD

This answer is no longer accurate; see below for other answers.

这个答案不再准确;其他答案见下文。

Sorry to break this on you, but I don't think there is a python-ldapfor Python 3 (yet)...

很抱歉打扰你,但我认为python-ldapPython 3(还)没有......

That's the reason why we should keep active development at Python 2.6 for now (as long as most crucial dependencies (libs) are not ported to 3.0).

这就是为什么我们现在应该在 Python 2.6 上保持积极开发的原因(只要大多数关键的依赖项(库)没有移植到 3.0)。

回答by Nikolai Saiko

You may use ldap3module (formerly known as python3-ldap), it runs on python3 really well and requires no external C dependances. Also it can correctly handle both unicode and byte data in ldap records (in early versions there was a trouble with jpegPhoto field, now everything is fine)

您可以使用ldap3模块(以前称为python3-ldap),它在 python3 上运行得非常好,不需要外部 C 依赖项。它还可以正确处理 ldap 记录中的 unicode 和字节数据(在早期版本中,jpegPhoto 字段有问题,现在一切正常)

回答by Todd

If you're running this on Windows, you can get LDAP to work in Python 3.1 by using the ADO access method via Mark Hammond's PyWin32.

如果您在 Windows 上运行它,您可以通过 Mark Hammond 的 PyWin32 使用 ADO 访问方法让 LDAP 在 Python 3.1 中工作。

To test this, I installed ActiveState Python 3.1, then installed PyWin32 for Python 3.1

为了测试这一点,我安装了 ActiveState Python 3.1,然后为 Python 3.1 安装了 PyWin32

http://sourceforge.net/projects/pywin32/files/

http://sourceforge.net/projects/pywin32/files/

I was then able to run LDAP queries using a module I wrote that is based on this LDAP code from the ActiveState Python Cookbook:

然后,我能够使用我编写的模块运行 LDAP 查询,该模块基于 ActiveState Python Cookbook 中的此 LDAP 代码:

Recipe 511451: Dump all Active Directory Information using LDAP scripting by Manuel Garcia

秘诀 511451:Manuel Garcia 使用 LDAP 脚本转储所有 Active Directory 信息

http://code.activestate.com/recipes/511451/

http://code.activestate.com/recipes/511451/

although now that I look at it I realize I completely rewrote my module just using his code as an example.

虽然现在我看到它,我意识到我只是使用他的代码作为示例完全重写了我的模块。



Update

更新

Here is my LDAPList module and another support module to convert user access bit codes into something a tiny bit more english-like:

这是我的 LDAPList 模块和另一个支持模块,用于将用户访问位代码转换为更像英语的东西:

LDAPList.py

LDAPList.py

# LDAPList.py
# Todd Fiske
# class to encapsulate accessing LDAP information

# 2009-03-18  first version
# 2010-01-04  updated for Python 3 (print functions, <> to !=)

import win32com.client
import UACCodes

ADS_SCOPE_SUBTREE = 2

class LDAPList():

  def __init__(self, sContext):
    self.Context = sContext # naming context, "DC=xyz,DC=org"

    self.objectCategory = ""
    self.objectClass = ""
    self.FilterClause = ""
    self.query = ""

    self.cn = None
    self.cm = None
    self.rs = None

  def SetCategory(self, sCategory):
    self.objectCategory = sCategory
    self.FilterClause = "where objectCategory = '%s'" % self.objectCategory

  def SetClass(self, sClass):
    self.objectClass = sClass
    self.FilterClause = "where objectClass = '%s'" % self.objectClass

  def open(self):
    self.query = "select * from 'LDAP://%s' %s order by displayName" % (self.Context, self.FilterClause)
    self.cn = win32com.client.Dispatch("ADODB.Connection")
    self.cm = win32com.client.Dispatch("ADODB.Command")

    self.cn.Open("Provider=ADsDSOObject")
    self.cm.ActiveConnection = self.cn
    self.cm.Properties["Page Size"] = 1000
    self.cm.Properties["Searchscope"] = ADS_SCOPE_SUBTREE

    self.cm.CommandText = self.query
    self.rs = self.cm.Execute()[0]

  def close(self):
    if self.rs is not None:
      self.rs.Close()
      self.rs = None

    if self.cm is not None:
      self.cm = None

    if self.cn is not None:
      self.cn.Close()
      self.cn = None

  def count(self):
    if self.rs is None:
      return -2
    return self.rs.RecordCount

  def more(self):
    if self.rs is None:
      return False
    return not self.rs.EOF

  def GetObject(self):
    if self.rs is None:
      return None
    return win32com.client.GetObject(self.rs.Fields["ADsPath"].Value)

  def next(self):
    if self.rs is None:
      return
    self.rs.MoveNext()

#----------

# helper functions

def NamingContext():
  # return default naming context
  root = win32com.client.GetObject("LDAP://RootDse")
  return root.get("DefaultNamingContext")

def AccountControl(obj):
  if obj.userAccountControl is not None:
    return obj.userAccountControl
  else:
    return 0

def ConvertUAC(nUAC):
  return UACCodes.ConvertUAC(nUAC)

def AccountActive(n):
  return (n & UACCodes.ADS_UF_ACCOUNTDISABLE) != UACCodes.ADS_UF_ACCOUNTDISABLE

def GetCategory(obj):
  # CN=Group,CN=Schema,CN=Configuration,DC=xyz,DC=org
  s = obj.objectCategory
  s = s.split(",")[0][3:]
  return s
  # s = "Group"

def GetGroups(obj):
  """
  ('CN=XYZ Staff Rockville,OU=Distribution Groups,DC=xyz,DC=org', 
  'CN=XYZ Staff,OU=Distribution Groups,DC=xyz,DC=org')
  """

  if obj.memberOf is None:
    return ""

  if type(obj.memberOf)==type(()):
    tGroups = obj.memberOf
  else:
    tGroups = (obj.memberOf,)
  return tGroups

def GetNameParts(obj):
  if obj.givenName is None:
    sFirst = ""
  else:
    sFirst = obj.givenName

  if obj.middleName is None:
    sMiddle = ""
  else:
    sMiddle = obj.middleName

  if obj.sn is None:
    sLast = ""
  else:
    sLast = obj.sn

  if sLast == "" and sFirst == "":
    if obj.name is not None:
      sName = obj.name
      sName = sName[3:]
      lParts = sName.split(" ")
      if len(lParts) == 1:
        "todo: split on embedded capital letter"
        print("single-part name: %s" % sName)
        sFirst = sName
      else:
        sLast = lParts[-1]
        sFirst = " ".join(lParts[:-1])

  return (sFirst, sMiddle, sLast)

def GetManager(obj):
  if obj.manager is None:
    return ""
  else:
    return obj.manager  

#----------

# test

if __name__ == "__main__":

  print
  print("testing LDAPList class")

  nc = NamingContext()
  print("context =", nc)

  ll = LDAPList(nc)
  ll.SetCategory('user')

  ll.open() # generates recordset
  print("query = %s" % ll.query)
  print("%d items" % ll.count())

  n = 0
  while (n < 10) and (ll.more()):
    o = ll.GetObject() # return 
    nUAC = AccountControl(o)
    print("%-30s  %-30s  %-30s  %-40s  %s" % (
      o.displayName, 
      o.name, 
      o.sAMAccountName, 
      UACCodes.ConvertUAC(nUAC), 
      GetManager(o)
    ))
    n += 1
    ll.next()

  ll.close()

###

UACCodes.py

UAC代码.py

# UACCodes.py
# Todd Fiske
# generated 2009-09-23 16:36:56 by BuildUACCodes.py
# updated 2010-01-04 for Python 3 (print functions)
# provide UAC constants, lookup list, and conversion function

import sys

# UAC Constants
ADS_UF_SCRIPT                                 = 0x00000001
ADS_UF_ACCOUNTDISABLE                         = 0x00000002
ADS_UF_HOMEDIR_REQUIRED                       = 0x00000008
ADS_UF_LOCKOUT                                = 0x00000010
ADS_UF_PASSWD_NOTREQD                         = 0x00000020
ADS_UF_PASSWD_CANT_CHANGE                     = 0x00000040
ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED        = 0x00000080
ADS_UF_TEMP_DUPLICATE_ACCOUNT                 = 0x00000100
ADS_UF_NORMAL_ACCOUNT                         = 0x00000200
ADS_UF_INTERDOMAIN_TRUST_ACCOUNT              = 0x00000800
ADS_UF_WORKSTATION_TRUST_ACCOUNT              = 0x00001000
ADS_UF_SERVER_TRUST_ACCOUNT                   = 0x00002000
ADS_UF_DONT_EXPIRE_PASSWD                     = 0x00010000
ADS_UF_MNS_LOGON_ACCOUNT                      = 0x00020000
ADS_UF_SMARTCARD_REQUIRED                     = 0x00040000
ADS_UF_TRUSTED_FOR_DELEGATION                 = 0x00080000
ADS_UF_NOT_DELEGATED                          = 0x00100000
ADS_UF_USE_DES_KEY_ONLY                       = 0x00200000
ADS_UF_DONT_REQUIRE_PREAUTH                   = 0x00400000
ADS_UF_PASSWORD_EXPIRED                       = 0x00800000
ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x01000000


# UAC short name lookup list
lUACCodes = [
  ("ADS_UF_SCRIPT"                                , 0x00000001, "script"),
  ("ADS_UF_ACCOUNTDISABLE"                        , 0x00000002, "disabled"),
  ("ADS_UF_HOMEDIR_REQUIRED"                      , 0x00000008, "homedir"),
  ("ADS_UF_LOCKOUT"                               , 0x00000010, "lockout"),
  ("ADS_UF_PASSWD_NOTREQD"                        , 0x00000020, "pwnotreqd"),
  ("ADS_UF_PASSWD_CANT_CHANGE"                    , 0x00000040, "pwcantchange"),
  ("ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED"       , 0x00000080, "encryptedpw"),
  ("ADS_UF_TEMP_DUPLICATE_ACCOUNT"                , 0x00000100, "dupaccount"),
  ("ADS_UF_NORMAL_ACCOUNT"                        , 0x00000200, "useracct"),
  ("ADS_UF_INTERDOMAIN_TRUST_ACCOUNT"             , 0x00000800, "interdomain"),
  ("ADS_UF_WORKSTATION_TRUST_ACCOUNT"             , 0x00001000, "workstation"),
  ("ADS_UF_SERVER_TRUST_ACCOUNT"                  , 0x00002000, "server"),
  ("ADS_UF_DONT_EXPIRE_PASSWD"                    , 0x00010000, "pwnoexpire"),
  ("ADS_UF_MNS_LOGON_ACCOUNT"                     , 0x00020000, "mnslogon"),
  ("ADS_UF_SMARTCARD_REQUIRED"                    , 0x00040000, "smartcard"),
  ("ADS_UF_TRUSTED_FOR_DELEGATION"                , 0x00080000, "trustdeleg"),
  ("ADS_UF_NOT_DELEGATED"                         , 0x00100000, "notdeleg"),
  ("ADS_UF_USE_DES_KEY_ONLY"                      , 0x00200000, "deskey"),
  ("ADS_UF_DONT_REQUIRE_PREAUTH"                  , 0x00400000, "nopreauth"),
  ("ADS_UF_PASSWORD_EXPIRED"                      , 0x00800000, "pwexpired"),
  ("ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION", 0x01000000, "trustauth"),
]


# UAC conversion function
def ConvertUAC(nUAC):
  s = ""
  for c in lUACCodes:
    if ((nUAC & c[1]) == c[1]):
      s = s + c[2] + " "
  return s

# test routine
if __name__ == "__main__":
  print("UACCodes Test")
  print("-------------")

  for n in [0, 512, 514, 65535]:
    print("%d = %s" % (n, ConvertUAC(n)))

  print
  for s in sys.argv[1:]:
    n = int(s)
    print("%d = %s" % (n, ConvertUAC(n)))

###

Both modules have some usage examples and should be fairly easy to figure out, but let me know if you have any questions or comments.

这两个模块都有一些使用示例,应该很容易理解,但如果您有任何问题或意见,请告诉我。

回答by Noufal Ibrahim

There is a Pure Python implementation of an LDAP client called Ldaptor. I don't think it's maintained though. If you really need it, you might be able to run 2to3 on this and port it.

有一个名为Ldaptor的 LDAP 客户端的纯 Python 实现。我认为它没有得到维护。如果你真的需要它,你可以在它上面运行 2to3 并移植它。