接以前个人文章,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安全