接以前個人文章,django+ldap+memcache實現單點登陸+統一認證 ,ldap部署相關,ldap雙機\LAM配置管理\ldap備份還原,目前來講,咱們已經有了高可用性的ldap環境了,裏邊也有了一些用戶信息,後邊要說一說經過django調用ldap的實現方式,裏邊主要涉及3個模塊,django-auth-ldap:用於從ldap同步帳戶、登陸驗證,它和ldap結合的很好,但它不能反向直接操做ldap,只能進行從ldap向下遊系統的同步,因此還須要python-ldap模塊,以便實現反向對ldap的增刪改查,我這邊的具體需求就是註冊用戶、重置密碼等,另外還須要一個python-memcached,用於把生成的session放到mc中
查了網上大量的關於django+ldap實現統一認證的文章,大部分都是隻寫了django-auth-ldap或者python-ldap來實現,可是若是要實現一套完整的統一認證系統,實際上這2個模塊都是須要的html
這個模塊,基本在settings.py經過配置就能夠拿來用了,基本不須要對代碼作什麼修改。用於從ldap裏拿到信息傳給sso系統作後續處理,但經過它沒法讓sso系統反向操做ldap,不管django的前臺和admin都適用
官方文檔: https://pythonhosted.org/django-auth-ldap/authentication.html
中文翻譯: https://darkcooking.gitbooks.io/django-auth-ldap/content/chapter9.html
不過這個翻譯版是個簡化版本,有的東西不全,不過基本也夠用了,而且網站打開很慢,我把它的pdf放在這裏,能夠自行查看 http://files.cnblogs.com/files/caseast/django-auth-ldap.pdf
django官網(session部分):https://docs.djangoproject.com/en/1.10/topics/http/sessions/
ok!直接上代碼吧,具體的配置說明,不明確的還請參考官方文檔,裏邊我把log模塊和session這部分配置也寫一下順道,不單獨開篇描述了
---settings.py---python
SESSION_ENGINE = "django.contrib.sessions.backends.cache" # 另外還有個cached_db,這兩個的區別是,cache只寫緩存,cached_db除了寫緩存還同時寫數據庫,若是對於session的安全性要求高能夠選擇cached_db SESSION_COOKIE_AGE = 86400 # 設置session有效期爲一天,默認兩週 SESSION_COOKIE_DOMAIN = ".ssotest.net" # 此配置不能解決跨域問題,可是能解決a.ssotest.net與b.ssotest.net的session共享問題,不加此屬性,跨站(非跨域)時,沒法傳遞session CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': [ # 鏈接的是2個mc,python-memcached自己有監活,掛一個mc會自動將請求分配到好的mc上 'ldap1.prod.bj1.ssotest.net:11211', 'ldap2.prod.bj1.ssotest.net:11211', ], 'TIMEOUT': 30, 'OPTIONS': { 'MAX_ENTRIES': 3000 } } } LOGIN_URL = "/account/login/" # ### ldap 配置部分BEGIN ### # import ldap from django_auth_ldap.config import LDAPSearch, PosixGroupType AUTHENTICATION_BACKENDS = ( 'django_auth_ldap.backend.LDAPBackend', # 配置爲先使用LDAP認證,如經過認證則再也不使用後面的認證方式 'django.contrib.auth.backends.ModelBackend', # sso系統中手動建立的用戶也可以使用,優先級靠後。注意這2行的順序 ) base_dn = 'dc=ldap,dc=ssotest,dc=net' AUTH_LDAP_SERVER_URI = 'ldap://ldap.ssotest.net' AUTH_LDAP_BIND_DN = 'uid=ssoadmin,ou=People,dc=ldap,dc=ssotest,dc=net' AUTH_LDAP_BIND_PASSWORD = 'ssotest@123' AUTH_LDAP_USER_SEARCH = LDAPSearch('ou=People,%s' % base_dn, ldap.SCOPE_SUBTREE, "(uid=%(user)s)") # 用戶的DN是uid=caojun,ou=People,dc=ldap,dc=ssotest,dc=net,因此用uid AUTH_LDAP_ALWAYS_UPDATE_USER = True # This is the default, but I like to be explicit. AUTH_LDAP_USER_ATTR_MAP = { # key爲數據庫字段名,value爲ldap中字段名,此字典解決django model與ldap字段名可能出現的不一致問題 "username": "uid", "name": "cn", "email": "mail" } # 組權限管理 # AUTH_LDAP_GROUP_SEARCH = LDAPSearch('ou=Group,dc=ldap,dc=ssotest,dc=net', ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)") AUTH_LDAP_GROUP_TYPE = PosixGroupType(name_attr="cn") # 組的DN是cn=員工,ou=Group,dc=ldap,dc=ssotest,dc=net,因此type是cn AUTH_LDAP_USER_FLAGS_BY_GROUP = { # django admin的is_staff|superuser屬性映射爲ldap的管理員 "is_staff": u"cn=管理員,ou=Group,dc=ldap,dc=ssotest,dc=net", "is_superuser": u"cn=管理員,ou=Group,dc=ldap,dc=ssotest,dc=net" } AUTH_LDAP_REQUIRE_GROUP = u"cn=員工,ou=Group,dc=ldap,dc=ssotest,dc=net" # 只有此group可用ldap進行認證 AUTH_LDAP_DENY_GROUP = u"cn=黑名單,ou=Group,dc=ldap,dc=ssotest,dc=net" # 此group不能使用ldap進行認證,直接deny掉,不會後續往django建立信息 AUTH_LDAP_MIRROR_GROUPS = True # 直接把ldap的組複製到django一份,和AUTH_LDAP_FIND_GROUP_PERMS互斥.用戶每次登陸會根據ldap來更新數據庫的組關係 # AUTH_LDAP_FIND_GROUP_PERMS = True # django從ldap的組權限中獲取權限,這種方式,django自身不建立組,每次請求都調用ldap # AUTH_LDAP_CACHE_GROUPS = True # 如打開FIND_GROUP_PERMS後,此配置生效,對組關係進行緩存,不用每次請求都調用ldap # AUTH_LDAP_GROUP_CACHE_TIMEOUT = 600 # 緩存時間 # ### ldap 配置部分END ### # # ### log 配置部分BEGIN ### # LDAP_LOGS = os.path.join(BASE_DIR, 'logs/ldap.log') stamdard_format = '[%(asctime)s][%(threadName)s:%(thread)d]' + \ '[task_id:%(name)s][%(filename)s:%(lineno)d] ' + \ '[%(levelname)s]- %(message)s' LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { # 詳細 'format': stamdard_format }, }, 'handlers': { 'default': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', 'filename': LDAP_LOGS, 'maxBytes': 1024 * 1024 * 100, # 5 MB 'backupCount': 5, 'formatter': 'standard', }, 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', } }, 'loggers': { '': { # default日誌,存放於log中 'handlers': ['default'], 'level': 'DEBUG', }, 'django_auth_ldap': { # django_auth_ldap模塊相關日誌打印到console 'handlers': ['console'], 'level': 'DEBUG', 'propagate': False, # 選擇關閉繼承,否則這個logger繼承自默認,日誌就會被記錄2次了(''一次,本身一次) }, # 'django.db.backends': { # 數據庫相關執行過程log打印到console # 'handlers': ['console'], # 'level': 'DEBUG', # }, } } # ### log 配置部分END ### #
logging模塊的說明,能夠參考這篇文章 http://www.jianshu.com/p/d615bf01e37b ,這個配置能夠配置到settings.py中,這樣django項目都會自動調用,或者單獨寫入一個log_config文件中,須要時手動調用,例子以下
log_config.pygit
import logging from logging.config import dictConfig logging_config={ ........ } dictConfig(logging_config) #註冊一下配置
調用方法:數據庫
import logging logger = logging.getLogger() logger.error('ldap conn失敗,緣由爲: %s' % str(e))
額外說一點,以上配置是在sso系統進行,若是下游系統接入到sso系統的話,順序就是ldap--> sso --> 項目A,默認接入後,項目A的前臺帳戶就可使用ldap進行管理,但項目A若是使用了django admin的話(由於前臺的登陸動做會強制轉到sso上,而admin若是不改源碼作不到這點),django admin是會走本地的帳戶的,這樣就會出現,一個下游系統的管理員用戶,前臺一個密碼,後臺一個密碼,因此咱們須要給下游系統的settings.py作必定配置,讓下游的admin帳戶也從ldap中同步,下游一樣須要開篇說的3個python模塊
項目A的settings.pydjango
# ### ldap 配置部分BEGIN (If use Django-admin,configure it!) ### # '''just for admin,前臺認證統一走認證平臺,因此下游系統不保存密碼,致使下游沒法登陸admin(如使用),因此admin添加ldap認證,只用ldap只讀帳戶便可''' import ldap from django_auth_ldap.config import LDAPSearch, PosixGroupType AUTHENTICATION_BACKENDS = ( 'django_auth_ldap.backend.LDAPBackend', # 配置爲先使用LDAP認證,如經過認證則再也不使用後面的認證方式 'django.contrib.auth.backends.ModelBackend', # 同時打開本地認證,由於下游系統的權限和組關係須要用到 ) base_dn = 'dc=ldap,dc=ssotest,dc=net' AUTH_LDAP_SERVER_URI = 'ldap://ldap.ssotest.net' AUTH_LDAP_BIND_DN = 'uid=ssoread,ou=People,dc=ldap,dc=ssotest,dc=net' # read only ldap user AUTH_LDAP_BIND_PASSWORD = 'ssotest@123' AUTH_LDAP_USER_SEARCH = LDAPSearch('ou=People,%s' % base_dn, ldap.SCOPE_SUBTREE, "(uid=%(user)s)") AUTH_LDAP_ALWAYS_UPDATE_USER = False # Default is True,是否登陸後從ldap同步用戶,不進行同步,由於下游的用戶表是什麼樣的不能肯定,只能肯定它也使用郵箱前綴 # 下游系統不從ldap同步group staff/superuser相關,但須要從ldap驗證用戶是否離職 AUTH_LDAP_GROUP_SEARCH = LDAPSearch('ou=Group,dc=ldap,dc=ssotest,dc=net', ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)") AUTH_LDAP_GROUP_TYPE = PosixGroupType(name_attr="cn") AUTH_LDAP_REQUIRE_GROUP = u"cn=員工,ou=Group,dc=ldap,dc=ssotest,dc=net" AUTH_LDAP_DENY_GROUP = u"cn=黑名單,ou=Group,dc=ldap,dc=ssotest,dc=net" AUTH_LDAP_FIND_GROUP_PERMS = True # django從ldap的組權限中獲取權限,這種方式,django自身不建立組,每次請求都調用ldap,下游子系統,咱們並不須要讓他同步ldap裏的"員工","管理員"這種表,因此不用mirror_groups AUTH_LDAP_CACHE_GROUPS = True # 如打開FIND_GROUP_PERMS後,才生效,對組關係進行緩存,不用每次請求都調用ldap AUTH_LDAP_GROUP_CACHE_TIMEOUT = 600 # ### ldap 配置部分END ### #
以上,咱們經過配置,就能夠完成django對於ldap的調用了,咱們能夠經過ldap來管理咱們的前臺和admin中的帳戶和密碼,可是這個動做是向下進行的,若是想經過咱們的單點登陸系統來操做ldap,這個django-auth-ldap是沒有這個功能的。這就須要後邊的python-ldap了.跨域
篇幅限制,python-ldap請參考個人這篇文章[原創]django+ldap實現統一認證部分二(python-ldap實踐)緩存
https://pythonhosted.org/django-auth-ldap/authentication.html
https://darkcooking.gitbooks.io/django-auth-ldap/content/chapter9.html
https://docs.djangoproject.com/en/1.10/topics/http/sessions/
http://www.jianshu.com/p/d615bf01e37b安全