如何在Django中使用LDAP

如何在Django中使用LDAP

什么是Django

Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的框架模式,即模型M,视图V和控制器C。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。(Django百科)

我们现在使用的Django版本的1.10,目前官网最新的是1.10.3

其他Django具体的学习教程请访问Django自强学堂

什么是LDAP

LDAP是轻量目录访问协议,英文全称是Lightweight Directory Access Protocol,一般都简称为LDAP。它是基于X.500标准的,但是简单多了并且可以根据需要定制。与X.500不同,LDAP支持TCP/IP,这对访问Internet是必须的。LDAP的核心规范在RFC中都有定义,所有与LDAP相关的RFC都可以在LDAPman RFC网页中找到。(LDAP百科)

如何在Django中使用LDAP

3.1 安装LDAP

  1. 直接pip安装,pip install ldap
  2. 如果你是windows操作系统,推荐一个网站Unofficial Windows Binaries for Python Extension Packages去下载whl文件,直接“pip install 包名字.whl”

3.2 在Django中使用LDAP
– 新建一个py文件,专门用来存放使用LDAP的代码,复制如下代码:

# encoding:utf-8
import ldap
LDAP_HOST = 'XXXXX'#ldap服务器地址
USER = 'XXXX'#ldap服务器用户名
PASSWORD = 'XXX'#ldap服务器密码
BASE_DN = 'dc=XXX,dc=xxx'#根目录


class LDAPTool:
    #初始化
    def __init__(self, ldap_host=None, base_dn=None, user=None, password=None):
        if not ldap_host:
            ldap_host = LDAP_HOST
        if not base_dn:
            self.base_dn = BASE_DN
        if not user:
            user = USER
        if not password:
            password = PASSWORD
        try:
            self.ldapconn = ldap.initialize(ldap_host)
            self.ldapconn.simple_bind_s(user, password)
        except ldap.LDAPError as e:
            print (e)

    #查找用户
    def ldap_search_dn(self, uid=None):
        obj = self.ldapconn
        obj.protocal_version = ldap.VERSION3
        searchScope = ldap.SCOPE_SUBTREE
        retrieveAttributes = None
        searchFilter = "sAMAccountName=" + uid
        try:
            ldap_result_id = obj.search(self.base_dn, searchScope, searchFilter, retrieveAttributes)
            result_set = []
            result_type, result_data = obj.result(ldap_result_id, 0)
            if result_type == ldap.RES_SEARCH_ENTRY:
                result_set.append(result_data)
                Name, Attrs = result_set[0][0]
                distinguishedName = Attrs['distinguishedName'][0]
                return distinguishedName
            else:
                # print (2)
                return None
        except ldap.LDAPError as e:
            print (e)

    #获取用户的一些属性
    def ldap_get_user(self, uid=None):
        obj = self.ldapconn
        obj.protocal_version = ldap.VERSION3
        searchScope = ldap.SCOPE_SUBTREE
        retrieveAttributes = None
        searchFilter = "sAMAccountName=" + uid
        try:
            ldap_result_id = obj.search(self.base_dn, searchScope, searchFilter, retrieveAttributes)
            result_type, result_data = obj.result(ldap_result_id, 0)
            if result_type == ldap.RES_SEARCH_ENTRY:
                if 'mail' in result_data[0][1].keys():
                    username = result_data[0][1]['cn'][0]
                    email = result_data[0][1]['mail'][0]
                    nick = result_data[0][1]['sn'][0]
                    displayname=result_data[0][1]['displayName'][0]
                else:
                    username = result_data[0][1]['cn'][0]
                    email = ''
                    nick = result_data[0][1]['sn'][0]
                    displayname=result_data[0][1]['displayName'][0]
                result = {'username': username, 'email': email, 'nick': nick,'displayname':displayname}
                return result
            else:
                return None
        except ldap.LDAPError as e:
            print (e)

    #验证用户名密码
    def ldap_get_vaild(self, uid=None, passwd=None):
        obj = self.ldapconn
        if self.ldap_search_dn(uid):
            try:
                target_cn="xx\\" + uid  #这里填写你的域名
                if obj.simple_bind_s(target_cn, passwd):
                    return True
                else:
                    return False
            # finally:
            #     return False
            except ldap.LDAPError as e:
                return False
        else:
            return False

    #更改密码
    def ldap_update_pass(self, uid=None, oldpass=None, newpass=None):
        modify_entry = [(ldap.MOD_REPLACE, 'userpassword', newpass)]
        obj = self.ldapconn
        target_cn = self.ldap_search_dn(uid)
        try:
            obj.simple_bind_s(target_cn, oldpass)
            obj.passwd_s(target_cn, oldpass, newpass)
            return True
        except ldap.LDAPError as e:
            print (e)
            return False



3.3 在Django中使用LDAP登录,在登录模块使用

from ADldap import *

def userlogin(request):
    post = request.POST
    username = post.get("Username")
    password = post.get("Password")
    try:
        if username == '' or password == '':
            return render_to_response("common/login.html", {"UserPwdNot": True})
        else:
            a =LDAPTool()
            username = str(username)
            password = str(password)
            userdn = a.ldap_search_dn(uid=username)
            if userdn:
                if a.ldap_get_vaild(uid=username, passwd=password):
                    request.session['username'] = username
                    return HttpResponseRedirect('/apply/')
                else:
                    return render_to_response("common/login.html", {"PassWordError": True})
            else:
                return render_to_response("common/login.html", {"UserNotExist": True})
    except Exception as e:
        print (e)

3.4其他的一些使用方法,可以用类似的方法:

#获取用户名字跟邮箱
a = LDAPTool()
userdn = a.ldap_search_dn(uid=username)
if userdn:
    userinfo=a.ldap_get_user(uid=username)
    adname=str(userinfo['nick'].decode('utf-8'))
    email=userinfo['email'].decode('utf-8')