Автентифікація проти активного каталогу за допомогою python + ldap


89

Як здійснити автентифікацію проти 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: {'info': '80090308: LdapErr: DSID-0C090334, коментар: Помилка AcceptSecurityContext, дані 52e, vece', 'desc': 'Недійсні облікові дані'}

Або

ldap.OPERATIONS_ERROR: {'info': '00000000: LdapErr: DSID-0C090627, коментар: Для виконання цієї операції необхідно виконати успішне прив'язування з'єднання., data 0, vece', 'desc': 'Помилка операцій '}

Що я втрачаю, щоб правильно пов’язати?

Я отримую ті самі помилки на Fedora та Windows.


2
"... і все, що воно виробляє, - це сльози". Є чи сльози римуються з ведмедями або Бірс?
philshem

Відповіді:


47

Я пропав безвісти

l.set_option(ldap.OPT_REFERRALS, 0)

З ініції.


3
Основною причиною цієї помилки є те, що у вас є посилання у початковій відповіді, а код LDAP Windows не надсилає облікові дані на сервер перенаправлення. Якщо ви використовували облікові дані kerberos, це мало б працювати.
schlenk

2
У мене були різні симптоми, але цей самий варіант вирішив мою проблему. Узагальнено у дописі в блозі: chaverma.com/blog/index.php/2013/06/…
Кріс,

Не впевнений, що пов’язаний, але у мене була та сама проблема, і, схоже, рішення 1729 щось зробило - Але іноді сервер LDAP просто негайно відповідає на НЕВІДИМІ КРЕДИТЕНТИ. Через деякий час він заспокоюється і працює знову.
Нітей

29

Якщо ви відкриті для використання pywin32, ви можете використовувати виклики Win32 від Python. Це те, що ми робимо на нашому веб-сервері CherryPy:

import win32security
token = win32security.LogonUser(
    username,
    domain,
    password,
    win32security.LOGON32_LOGON_NETWORK,
    win32security.LOGON32_PROVIDER_DEFAULT)
authenticated = bool(token)

3
просто і чисто! Дякую!
alexroat

Це рішення працювало для мене в додатку Python Flask, перебуваючи за обмеженим корпоративним проксі NTLM. Деякі інші опції на основі LDAP просто не працюють.
Гігафлоп,

7

Це працювало для мене, l.set_option (ldap.OPT_REFERRALS, 0) був ключем до доступу до ActiveDirectory. Більше того, я думаю, що вам слід додати "con.unbind ()", щоб закрити з'єднання перед завершенням сценарію.


8
З документації python-ldap : Екземпляри LDAPObjectповертаються initialize(). З’єднання автоматично роз’єднується і закривається, коли об’єкт LDAP видаляється.
Søren Løvborg

Ви закриваєте сеанс, а не з'єднання.
Ромул

5

Ось простий код, який мені підходить.

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")

Це базується на попередній відповіді .


1
Це вже не працює, ви отримаєтеAttributeError: module 'ldap' has no attribute 'open'
Джош Коррея

3

якщо у вас встановлений 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)


2

Я бачу ваш коментар @Johan Buret про те, що DN не вирішує вашу проблему, але я також вважаю, що вам слід розглянути це.

На вашому прикладі, DN для облікового запису адміністратора за замовчуванням в AD буде: cn = Administrator, cn = Users, dc = mydomain, dc = co, dc = uk - спробуйте це.


2

На основі чудового підручника 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.


1

Я намагався додати

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, і екземпляр зареєстровано для поточного рахунку.


1

У мене була та ж проблема, але це стосувалось кодування пароля

.encode('iso-8859-1')

Вирішив проблему.


0

Використовуйте визначне ім’я, щоб увійти до системи. "CN=Your user,CN=Users,DC=b2t,DC=local" Він повинен працювати на будь-якій системі LDAP, включаючи AD


0

Для мене перехід від simple_bind_s()до bind()зробив трюк.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.