最近项目需求,要实现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)