Аутентификация в активном каталоге с использованием Python + ldap
-
02-07-2019 - |
Вопрос
Как мне пройти аутентификацию в AD с помощью Python + LDAP.В настоящее время я использую библиотеку python-ldap, и все, что она производит, — это слезы.
Я даже не могу выполнить привязку для выполнения простого запроса:
import sys
import ldap
Server = "ldap://my-ldap-server"
DN, Secret, un = sys.argv[1:4]
Base = "dc=mydomain,dc=co,dc=uk"
Scope = ldap.SCOPE_SUBTREE
Filter = "(&(objectClass=user)(sAMAccountName="+un+"))"
Attrs = ["displayName"]
l = ldap.initialize(Server)
l.protocol_version = 3
print l.simple_bind_s(DN, Secret)
r = l.search(Base, Scope, Filter, Attrs)
Type,user = l.result(r,60)
Name,Attrs = user[0]
if hasattr(Attrs, 'has_key') and Attrs.has_key('displayName'):
displayName = Attrs['displayName'][0]
print displayName
sys.exit()
Запускаем это с myusername@mydomain.co.uk password username
выдает мне одну из двух ошибок:
Invalid Credentials
- Когда я опечатываюсь или намеренно использую неверные учетные данные, аутентификация невозможна.
ldap.INVALID_CREDENTIALS:{'Информация':'80090308:ЛдапЭрр:DSID-0C090334, комментарий:Ошибка AcceptSecurityContext, данные 52e, vece', 'desc':«Неверные учетные данные»}
Или
ldap.OPERATIONS_ERROR:{'Информация':'00000000:ЛдапЭрр:DSID-0C090627, комментарий:Для выполнения этой операции необходимо завершить успешную привязку соединения., data 0, vece', 'desc':'Ошибка операции'}
Что мне не хватает для правильной привязки?
Я получаю одни и те же ошибки в Fedora и Windows.
Решение
я пропал без вести
l.set_option(ldap.OPT_REFERRALS, 0)
Из инициализации.
Другие советы
Если вы готовы использовать pywin32, вы можете использовать вызовы Win32 из Python.Вот что мы делаем на нашем веб-сервере CherryPy:
import win32security
token = win32security.LogonUser(
username,
domain,
password,
win32security.LOGON32_LOGON_NETWORK,
win32security.LOGON32_PROVIDER_DEFAULT)
authenticated = bool(token)
Это сработало для меня, l.set_option(ldap.OPT_REFERRALS, 0) был ключом для доступа к ActiveDirectory.Более того, я думаю, вам следует добавить «con.unbind()», чтобы закрыть соединение до завершения сценария.
Вот простой код, который работает для меня.
import ldap # run 'pip install python-ldap' to install ldap module.
conn = ldap.open("ldaphost.company.com")
conn.simple_bind_s("myuser@company.com", "mypassword")
Это основано на предыдущий ответ.
Если у вас установлен Kerberos и вы взаимодействуете с AD, как, скажем, в случае, если установлен и запущен Centrify Express, вы можете просто использовать python-kerberos.Например.
import kerberos
kerberos.checkPassword('joe','pizza','krbtgt/x.pizza.com','X.PIZZA.COM')`
вернет значение True, если у пользователя «joe» есть пароль «pizza» в области Kerberos X.PIZZA.COM.(обычно, я думаю, последнее будет таким же, как имя домена AD)
Я вижу ваш комментарий @Johan Buret о том, что DN не решает вашу проблему, но я также считаю, что вам следует обратить на это внимание.
В вашем примере DN для учетной записи администратора по умолчанию в AD будет:cn=Administrator,cn=Users,dc=mydomain,dc=co,dc=uk — попробуйте это.
Я попытался добавить
l.set_option(ldap.OPT_REFERRALS, 0)
но вместо ошибки Python просто зависает и больше ни на что не реагирует.Может я неправильно строю поисковый запрос, что такое Базовая часть поиска?Я использую то же самое, что и DN, для простой привязки (о, и мне пришлось это сделать l.simple_bind
, вместо l.simple_bind_s
):
import ldap
local = ldap.initialize("ldap://127.0.0.1")
local.simple_bind("CN=staff,DC=mydomain,DC=com")
#my pc is not actually connected to this domain
result_id = local.search("CN=staff,DC=mydomain,DC=com", ldap.SCOPE_SUBTREE, "cn=foobar", None)
local.set_option(ldap.OPT_REFERRALS, 0)
result_type, result_data = local.result(result_id, 0)
Я использую AD LDS, и экземпляр зарегистрирован для текущей учетной записи.
У меня была такая же проблема, но она касалась кодировки пароля.
.encode('iso-8859-1')
Решил проблему.
На основе отличного руководство по ldap3:
>>> from ldap3 import Server, Connection, ALL, NTLM
>>> server = Server('server_name_or_ip', get_info=ALL)
>>> conn = Connection(server, user="user_name", password="password", auto_bind=True)
>>> conn.extend.standard.who_am_i()
>>> server.info
Я сделал это в Python3, но предполагается, что оно совместимо с Python 2.
Используйте отличительное имя для входа в систему."CN=Your user,CN=Users,DC=b2t,DC=local"
Он должен работать в любой системе LDAP, включая AD.
Для меня переход от simple_bind_s()
к bind()
сделал свое дело.