天天看點

Django實作AD域內建Python實作AD域內建

Python實作AD域內建

本片文章簡單介紹一下django項目中的AD域內建業務邏輯實作。

AD域

  • “AD域可用于同時管理多台電腦,這樣實作集中式管理,可以很大程度減少管理者的工作量。比如曾經我們需要在無數用戶端上進行多次的設定,在AD域控制器上隻需要設定一次就能完成。”

實作過程

  1. 使用第三方工具:

    ldap

    這是一種通信協定。
  2. 安裝python-ldap,不同的環境使用的ldap不同,python2.7和python3.7略有不同。
  3. 了解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        
           
  1. 了解使用方法之後,做一些使用者驗證,驗證成功後将資料儲存。
一個簡單的驗證,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
           

具體儲存什麼資料,驗證方式還需要業務邏輯.