最近項目需求,要實現LDAP認證方式,上網找了一下,大致的方式就是使用django-auth-ldap 和 python-ldap這兩個第三庫。實現方法如下:
1. pip install python-ldap django-auth-ldap
筆者的環境是centos6, 在windows上安裝 python-ldap會出問題
2.配置django的settings.py檔案
AUTHENTICATION_BACKENDS = ( 'django_auth_ldap.backend.LDAPBackend', # ldap認證 'django.contrib.auth.xxxx.xxxxx', # 本地預設的認證方式 )
AUTH_LDAP_SERVER_URI = "ldap://127.0.0.1" # ldap伺服器位址 AUTH_LDAP_BIND_DN = '' # 可為空白,也可以填寫一個真實的ldap使用者 AUTH_LDAP_BIND_PASSWORD = '' AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=test,dc=test,dc=com", ldap.SCOPE_SUBTREE, "(cn=%(user)s)") # 第一個參數是搜尋的範圍 AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", "last_name": "sn", "username": "sn"} AUTH_LDAP_ALWAYS_UPDATE_USER = True這樣配置之後,使用者登入的時候先進行ldap認證,當ldap認證失敗後,會走本地預設的認證方式。但是這種方式有個缺點,就是ldap的配置發生改變,就需要改settings.py,有點麻煩。後來把ldap的配置在網頁裡配置,然後把ldap配置資訊寫進資料庫,這樣一來就要改python-auth-ldap的源碼了,讓它從資料庫中讀取ldap的配置資訊。
把django-auth-ldap的源碼包放進項目中,修改backends.py檔案, 讓原來從settings設定檔讀取的值從資料庫讀。
class LDAPSettings(object): """ This is a simple class to take the place of the global settings object. An instance will contain all of our settings as attributes, with default values if they are not specified by the configuration. """ defaults = { 'ALWAYS_UPDATE_USER': True, 'AUTHORIZE_ALL_USERS': False, 'BIND_AS_AUTHENTICATING_USER': False, 'BIND_DN': '', 'BIND_PASSWORD': '', 'CACHE_GROUPS': False, 'CONNECTION_OPTIONS': {}, 'DENY_GROUP': None, 'FIND_GROUP_PERMS': False, 'GROUP_CACHE_TIMEOUT': None, 'GROUP_SEARCH': None, 'GROUP_TYPE': None, 'MIRROR_GROUPS': False, 'PERMIT_EMPTY_PASSWORD': False, 'PROFILE_ATTR_MAP': {}, 'PROFILE_FLAGS_BY_GROUP': {}, 'REQUIRE_GROUP': None, 'SERVER_URI': 'ldap://localhost', 'START_TLS': False, 'USER_ATTRLIST': None, 'USER_ATTR_MAP': {}, 'USER_DN_TEMPLATE': None, 'USER_FLAGS_BY_GROUP': {}, 'USER_SEARCH': None, } def __init__(self, prefix='AUTH_LDAP_', defaults={}): """ Loads our settings from django.conf.settings, applying defaults for any that are omitted. """ import ldap defaults = dict(self.defaults, **defaults) ldap_auth_info = AuthSettings.objects.filter(is_delete=False).first() ldap_info_db = {"SERVER_URI": "ldap_server_uri", "BIND_DN": "ldap_bind_dn", "BIND_PASSWORD": "ldap_bind_passwd", "USER_SEARCH": "ldap_user_search"} for name, default in defaults.items(): if name in ldap_info_db.keys(): if name == "SERVER_URI": db_attr = ldap_info_db.get(name) value = getattr(ldap_auth_info, db_attr) + ":" + str(getattr(ldap_auth_info, "ldap_server_port")) elif name == "USER_SEARCH": rdn = "(cn=%(user)s)" if ldap_auth_info.ldap_user_search == "cn" else "(uid=%(user)s)" value = LDAPSearch(ldap_auth_info.ldap_based_dn, ldap.SCOPE_SUBTREE, rdn) else: db_attr = ldap_info_db.get(name) value = getattr(ldap_auth_info, db_attr) else: value = getattr(django.conf.settings, prefix + name, default) setattr(self, name, value)