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
具体保存什么数据,验证方式还需要业务逻辑.