There are many intranet systems in the company. If each system has an independent login account, the company leader may have an opinion. In order to solve the problem of too many accounts, the login mode can adopt domain authentication. Here we share python's domain authentication and account synchronization through ldap3.
First download ldap3 via pip
pip install ldap3
Synchronize the information in the domain to the database and code it
from ldap3 import Server, Connection, ALL, SUBTREE, ServerPool import MySQLdb import re import datetime LDAP_SERVER_POOL = ['xx.xx.xx.xx'] #ip address of domain control server LDAP_SERVER_PORT = 389 #port ADMIN_DN = 'xxx@xxx.xx' #Domain account with query authority ADMIN_PASSWORD = 'xxxxx' #The corresponding password SEARCH_BASE = 'ou=Organization name,dc=xxx,dc=xx' def connect_sql(): db = MySQLdb.connect('localhost', 'root', 'password', 'databasename', charset='utf8') return db def ldap_sync(): ldap_server_pool = ServerPool(LDAP_SERVER_POOL) conn = Connection(ldap_server_pool, user=ADMIN_DN, password=ADMIN_PASSWORD, check_names=True, lazy=False, raise_exceptions=False) conn.open() conn.bind() res = conn.search( search_base = SEARCH_BASE, search_filter = '(objectclass=user)',#Query all users search_scope = SUBTREE, attributes = ['cn', 'sn', 'givenName', 'mail', 'sAMAccountName'] #cn user's Chinese name, sn surname, givenName name, mail mail, sAMAccountName is account number. ) db = connect_sql() cursor = db.cursor() if res: print('sync start') #print(len(conn.response)) for entry in conn.response: dn = entry['dn'] #dn contains ou information dc information and so on, which can be used as authentication account when doing domain verification login. dict_attr = entry['attributes'] cn = dict_attr['cn'] sn = dict_attr['sn'] givenName = dict_attr['givenName'] mail = dict_attr['mail'] sAMAccountName = dict_attr['sAMAccountName'] # Here's the second part of the company's department name from ou information in dn ous = re.findall(r'OU=([^,]+),', str(dn)) dep = ous[1] #print(dep) # Departmental id in database based on department name sql = 'select id from itassets_department where\ name="{}";'.format(dep) cursor.execute(sql) data = cursor.fetchone() if data is None: # This department does not exist in the database, so insert operation can be considered. print('department is not exist: %s' %(dep)) continue dep_id = data[0] # user exist? sql = 'select id from itassets_myuser where \ username="{}";'.format(sAMAccountName) cursor.execute(sql) user = cursor.fetchone() if user: # Update user information if the user exists, otherwise insert operation print('update user %s%s' % (sn, givenName)) user_id = user[0] sql = 'update itassets_myuser set \ first_name="{}", last_name="{}", email="{}", name="{}", \ dep_id="{}" where id="{}"'.format(givenName, sn, mail, cn, dep_id, user_id) try: cursor.execute(sql) db.commit() except Exception as e: print(e) db.rollback() else: print('insert user %s' % (cn)) # Create user information dt = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S') #print(dt) sql = 'insert into itassets_myuser(password, is_superuser,\ username, first_name, last_name, email, is_staff, is_active,\ date_joined, name, dep_id, login_mode) values ("%s", 0, "%s","%s",\ "%s", "%s", 1, 1, "%s", "%s", %d, 2);' % (' ', sAMAccountName, givenName, sn, mail, dt, cn, int(dep_id)) try: cursor.execute(sql) db.commit() except Exception as e: print(e) db.rollback() print('sync complete') #print(conn.entries) else: print('search faild') db.close() if __name__ == '__main__': ldap_sync()
The code is very simple. The contents of the synchronization are changed according to the needs of the sql statement. But what information is provided by the AD domain, so we can go to search it.
Domain validation is understood as a few simple steps: 1. login the domain account with query privileges first; 2. query the user name of the current login operation, that is, the dn of sAMAccountName in the domain; 3. use dn and password to connect, and return the response ['description']='success'to log in successfully. The code is as follows:
ldap_server_pool = ServerPool(LDAP_SERVER_POOL) conn = Connection(ldap_server_pool, user=ADMIN_DN, password=ADMIN_PASSWORD, check_names=True, lazy=False, raise_exceptions=False) conn.open() conn.bind() res = conn.search( search_base = SEARCH_BASE, search_filter = '(sAMAccountName=lancy01)', search_scope = SUBTREE, ) if res: dn = conn.response[0]['dn'] try: conn2 = Connection(ldap_server_pool, user=username, password=password, check_names=True, lazy=False, raise_exceptions=False) conn2.bind() if conn2.result['description'] == 'success': # Represents successful validation pass else: pass except pass
Very simple, welcome to correct