Python實作AD域內建
本片文章簡單介紹一下django項目中的AD域內建業務邏輯實作。
AD域
- “AD域可用于同時管理多台電腦,這樣實作集中式管理,可以很大程度減少管理者的工作量。比如曾經我們需要在無數用戶端上進行多次的設定,在AD域控制器上隻需要設定一次就能完成。”
實作過程
- 使用第三方工具:
這是一種通信協定。ldap
- 安裝python-ldap,不同的環境使用的ldap不同,python2.7和python3.7略有不同。
- 了解ldap增删改查
查找和讀取一條 LDAP 紀錄,比如根據 username 查找出 cn:
def ldap_getcn(username):
try:
l = ldap.open(LDAP_HOST)
l.protocol_version = ldap.VERSION3
l.simple_bind(LDAP_BIND, LDAP_PASS)
searchScope = ldap.SCOPE_SUBTREE
searchFilter = "uid=*" + username + "*"
resultID = l.search(LDAP_BASE, searchScope, searchFilter, None)
result_set = []
while 1:
result_type, result_data = l.result(resultID, 0)
if (result_data == []):
break
else:
if result_type == ldap.RES_SEARCH_ENTRY:
result_set.append(result_data)
return result_set[0][0][1]['cn'][0]
except ldap.LDAPError, e:
print e
更新一條 LDAP 紀錄,比如更新使用者狀态 active 為 false:
def ldap_deactive(username):
try:
l = ldap.open(LDAP_HOST)
l.protocol_version = ldap.VERSION3
l.simple_bind(LDAP_BIND, LDAP_PASS)
deactiveDN = ("cn=%s," + LDAP_BASE) % ldap_getcn(username)
old = {'active':'TRUE'}
new = {'active':'FALSE'}
ldif = modlist.modifyModlist(old, new)
l.modify_s(deactiveDN, ldif)
l.unbind_s()
except ldap.LDAPError, e:
print e
删除一條 LDAP 紀錄:
def ldap_delete(username):
try:
l = ldap.open(LDAP_HOST)
l.protocol_version = ldap.VERSION3
l.simple_bind(LDAP_BIND, LDAP_PASS)
deleteDN = ("cn=%s," + LDAP_BASE) % ldap_getcn(username)
l.delete_s(deleteDN)
except ldap.LDAPError, e:
print e
- 了解使用方法之後,做一些使用者驗證,驗證成功後将資料儲存。
一個簡單的驗證,django登陸是調用就可以。
import ldap
class LDAPBackend(object):
"""
Authenticates with ldap.
"""
_connection = None
_connection_bound = False
def authenticate(self, username=None, passwd=None, **kwargs):
if not username or not passwd:
return None
if self._authenticate_user_dn(username, passwd):
user = self._get_or_create_user(username, passwd)
return user
else:
return None
@property
def connection(self):
if not self._connection_bound:
self._bind()
return self._get_connection()
def _bind(self):
self._bind_as(
LDAP_CONFIG['USERNAME'], LDAP_CONFIG['PASSWORD'], True
)
def _bind_as(self, bind_dn, bind_password, sticky=False):
self._get_connection().simple_bind_s(
bind_dn, bind_password
)
self._connection_bound = sticky
def _get_connection(self):
if not self._connection:
self._connection = ldap.initialize(LDAP_CONFIG['HOST'])
return self._connection
def _authenticate_user_dn(self, username, passwd):
bind_dn = 'cn=%s,%s' % (username, LDAP_CONFIG['BASE_DN'])
try:
self._bind_as(bind_dn, passwd, False)
return True
except ldap.INVALID_CREDENTIALS:
return False
def _get_or_create_user(self, username, passwd):
# 擷取或者建立User
return user
具體儲存什麼資料,驗證方式還需要業務邏輯.