Xác thực thư mục hoạt động bằng python + ldap


89

Làm cách nào để xác thực AD bằng Python + LDAP. Tôi hiện đang sử dụng thư viện python-ldap và tất cả những gì nó tạo ra là những giọt nước mắt.

Tôi thậm chí không thể liên kết để thực hiện một truy vấn đơn giản:

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

Chạy cái này với myusername@mydomain.co.uk password usernametôi mắc một trong hai lỗi:

Invalid Credentials - Khi tôi nhập sai hoặc cố ý sử dụng thông tin đăng nhập sai, nó không thể xác thực.

ldap.INVALID_CREDENTIALS: {'info': '80090308: LdapErr: DSID-0C090334, nhận xét: Lỗi AcceptSecurityContext, dữ liệu 52e, vece', 'desc': 'Thông tin đăng nhập không hợp lệ'}

Hoặc là

ldap.OPERATIONS_ERROR: {'info': '00000000: LdapErr: DSID-0C090627, nhận xét: Để thực hiện thao tác này, bạn phải hoàn thành liên kết thành công trên kết nối., data 0, vece', 'desc': 'Lỗi thao tác '}

Tôi đang thiếu điều gì để ràng buộc đúng cách?

Tôi đang gặp các lỗi tương tự trên fedora và windows.


2
"... và tất cả những gì nó tạo ra là nước mắt." Có nước mắt vần với Bears hoặc Beers?
philshem

Câu trả lời:


47

tôi đã mất tích

l.set_option(ldap.OPT_REFERRALS, 0)

Từ init.


3
Nguyên nhân gốc rễ của lỗi này là do bạn có giới thiệu trong phản hồi ban đầu và mã LDAP của windows không gửi thông tin đăng nhập đến máy chủ giới thiệu. Nếu bạn sử dụng thông tin đăng nhập kerberos, nó sẽ hoạt động.
schlenk 17/12/09

2
Tôi có các triệu chứng khác nhau nhưng cùng một lựa chọn này đã khắc phục được sự cố của tôi. Tóm tắt nó trong một bài đăng trên blog: chaverma.com/blog/index.php/2013/06/…
Chris

Không chắc liệu có liên quan hay không, nhưng tôi đã gặp phải vấn đề tương tự và có vẻ như giải pháp của 1729 đã làm được điều gì đó - Nhưng đôi khi máy chủ LDAP chỉ trả lời ngay lập tức. Sau một thời gian nó sẽ dịu lại và hoạt động trở lại.
Nitay

28

Nếu bạn sẵn sàng sử dụng pywin32, bạn có thể sử dụng lệnh gọi Win32 từ Python. Đây là những gì chúng tôi làm trong máy chủ web CherryPy của mình:

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

3
đơn giản và sạch sẽ! Cảm ơn!
alexroat

Giải pháp này phù hợp với tôi trong ứng dụng Python Flask trong khi đằng sau proxy công ty NTLM hạn chế. Một số tùy chọn dựa trên LDAP khác sẽ không hoạt động.
Gigaflop

7

Điều đó phù hợp với tôi, l.set_option (ldap.OPT_REFERRALS, 0) là chìa khóa để truy cập ActiveDirectory. Hơn nữa, tôi nghĩ rằng bạn nên thêm một "con.unbind ()" để đóng kết nối trước khi hoàn thành tập lệnh.


8
Từ tài liệu python-ldap : Các phiên bản của LDAPObjectđược trả về bởi initialize(). Kết nối tự động được bỏ gắn và đóng khi đối tượng LDAP bị xóa.
Søren Løvborg

Bạn đóng phiên, không phải kết nối.
Romulus

5

Đây là một số mã đơn giản phù hợp với tôi.

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

Điều này dựa trên một câu trả lời trước đó .


1
Điều này không hoạt động nữa, bạn sẽ nhận đượcAttributeError: module 'ldap' has no attribute 'open'
Josh Correia

3

nếu bạn đã cài đặt Kerberos và nói chuyện với AD, giống như trường hợp của Centrify Express được cài đặt và chạy, bạn có thể chỉ cần sử dụng python-kerberos. Ví dụ

import kerberos
kerberos.checkPassword('joe','pizza','krbtgt/x.pizza.com','X.PIZZA.COM')`

sẽ trả về True một người dùng 'joe' có mật khẩu 'pizza' trong lĩnh vực Kerberos X.PIZZA.COM. (thông thường, tôi nghĩ, tên sau sẽ giống với tên của Miền quảng cáo)


2

Tôi thấy nhận xét của bạn với @Johan Buret về việc DN không khắc phục được sự cố của bạn, nhưng tôi cũng tin rằng đó là điều bạn nên xem xét.

Với ví dụ của bạn, DN cho tài khoản quản trị viên mặc định trong AD sẽ là: cn = Administrator, cn = Users, dc = mydomain, dc = co, dc = uk - hãy thử điều đó.


2

Dựa trên hướng dẫn ldap3 tuyệt vời :

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

Tôi đã làm những điều trên bằng Python3 nhưng nó phải tương thích với Python 2.


1

Tôi đã cố gắng thêm

l.set_option (ldap.OPT_REFERRALS, 0)

nhưng thay vì một lỗi, Python chỉ bị treo và sẽ không phản hồi bất kỳ điều gì nữa. Có thể tôi đang xây dựng truy vấn tìm kiếm sai, Phần cơ bản của tìm kiếm là gì? Tôi đang sử dụng giống như DN cho ràng buộc đơn giản (ồ, và tôi phải làm l.simple_bind, thay vì 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)

Tôi đang sử dụng AD LDS và phiên bản đã được đăng ký cho tài khoản hiện tại.


1

Tôi đã gặp vấn đề tương tự, nhưng nó liên quan đến mã hóa mật khẩu

.encode('iso-8859-1')

Đã giải quyết vấn đề.


0

Sử dụng Tên phân biệt để đăng nhập vào hệ thống của bạn. "CN=Your user,CN=Users,DC=b2t,DC=local" Nó sẽ hoạt động trên bất kỳ hệ thống LDAP nào, bao gồm cả AD


0

Đối với tôi thay đổi từ simple_bind_s()đến bind()đã làm các trick.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.