zoukankan      html  css  js  c++  java
  • Django用openLDAP做认证

    前言

    之前有需求要做一个django+ldap用户管理的简单接口,研究了好几个模块,最后终于能实现django用ldap做用户认证了。也是自己的水平有限吧,做了好长时间,现在就和大家分享一下这个过程吧。最终是有两种方法实现这个认证过程,一种是通过django-python3-ldap实现的,一种是自己写了一个简单的。我下面有个示例程序在github上面,这个程序是两个方法都能用,而且我放到了一个django的app下。大家可以下载下来看看。

    基本信息

    具体如下:
    python pip信息:

    bogon:ldapdemo hongzhi.wang$ pip list|egrep -i 'django|ldap'
    Django                                 1.8.11
    django-auth-ldap                       1.2.9
    django-bootstrap-form                  3.2.1
    django-celery                          3.1.16
    django-crontab                         0.7.1
    django-python3-ldap                    0.9.11
    djangorestframework                    3.6.2
    ldap3                                  1.4.0
    python-ldap                            2.4.32
    

    ldap 相关信息(在我自己的虚拟机上面搭的):

    192.168.3.3:389
    dn: cn=user03,ou=People,dc=node1,dc=com secret:555
    dn: cn=user02,ou=People,dc=node1,dc=com secret:555
    dn: cn=user01,ou=People,dc=node1,dc=com secret:555
    

    user02的详细信息

    dn: cn=user02,ou=People,dc=node1,dc=com
    objectClass: posixAccount
    objectClass: inetOrgPerson
    objectClass: organizationalPerson
    objectClass: person
    homeDirectory: /home/user02
    loginShell: /bin/bash
    uid: user02
    cn: user02
    uidNumber: 10002
    gidNumber: 100
    sn: user02
    mail: user02@qq.com
    userPassword:: e1NTSEF9WEZXOWMxaFZFMjVaK3JnV3Q3a1FDWW0wdWxjRVZrVk8=
    

    示例程序地址在此:https://github.com/WisWang/ldapdemo

    目录结构如下:

    bogon:PycharmProjects hongzhi.wang$ tree ldapdemo/|grep -v pyc
    ldapdemo/
    ├── db.sqlite3
    ├── ldapdemo
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   ├── wsgi.py
    ├── manage.py
    ├── my_ldap_auth
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── django_python3_ldap_settings.py
    │   ├── ldap_tool.py
    │   ├── migrations
    │   │   ├── __init__.py
    │   ├── models.py
    │   ├── mysettings.py
    │   ├── tests.py
    │   ├── urls.py
    │   ├── views.py
    ├── static
    │   ├── css
    │   │   ├── bootstrap.css
    │   │   ├── bootstrap.min.css
    │   │   └── custom.css
    │   └── js
    │       ├── bootstrap.js
    │       ├── bootstrap.min.js
    │       └── jquery-2.2.2.js
    └── templates
        ├── home.html
        ├── ldap_auth.html
        └── login_content.html
    

    本次还用了django-python3-ldap

    我自己实现的python+django认证

    基本思路就是通过python-ldap这个模块自己封装了一个类,然后实现各种用到的方法,
    认证过程就是拿到用户名密码后,先通过这个ldapdemo/my_ldap_auth/ldap_tool.py里的如下方法验证用户名存不存在,存在返回这个用户的dn(这种方法缺点是用户名在这个basedn下面必须唯一,不过可以通过让用户输入部门名输入到后台,然后再search的时候添加ou筛选就能实现用户在不同部门但是用户名相同的认证,本文就再多做叙述了。)

    def check_user(self, username):
        self.conn.simple_bind_s(USER, PASSWORD)
        filter = '(uid=%s)' % username
        attrs = ['sn', 'uid']
        ret = self.conn.search_s(BASE_DN, ldap.SCOPE_SUBTREE, filter, attrs)
        if ret:
            return ret[0][0]
        else:
            return False
    

    拿到用户名后self.conn.simple_bind_s(dn,userpass)这样去server端检查用户名,密码。
    然后就是这段代码了ldapdemo/my_ldap_auth/views.py

    ldaptool = LdapTool()
    res = ldaptool.check_pass(username,password)
    #res这个放回值是我自定义的,详见代码吧
    if res == 0:
        user = User.objects.filter(username=username)
        if not user:
            u = User.objects.create_user(username=username, password="asdf1234")
        else:
            u = user[0]
            u.set_password("asdf1234")
        u.save()
        user = authenticate(username=username, password='asdf1234')
        login(request, user)
        return HttpResponseRedirect('/')
    elif res == 1:
        err_msg = "username not found"
    else:
        err_msg = "password wrong"
    return render(request, 'ldap_auth.html', {'err_msg': err_msg, })
    

    基本思路就是ldap验证通过以后,检查django默认的User表有没有这个用户,没有就创建,然后把这个用户登录。(这个是每次有用户认证都会和ldapserver建立一个连接,之前是在django启动的时候我就建立一个连接,各有优缺点吧。)

    通过django-python3-ldap实现的认证

    这个基本就是按照这个django-python3-ldap在github上面那个readme来做的,但是遇到些问题,我把原来的代码改了一处,就能用了,但是感觉限制有些多,下面就来说一下吧。
    在配置文件中有如下配置

    # The LDAP username and password of a user for authenticating the `ldap_sync_users`
    # management command. Set to None if you allow anonymous queries.
    LDAP_AUTH_CONNECTION_USERNAME = "admin"
    LDAP_AUTH_CONNECTION_PASSWORD = "secret"
    

    ./manage.py ldap_sync_users这样同步用户的时候,由于这个配置一下配置:

    # The LDAP search base for looking up users.
    LDAP_AUTH_SEARCH_BASE = "ou=people,dc=example,dc=com"
    
    # User model fields mapped to the LDAP
    # attributes that represent them.
    LDAP_AUTH_USER_FIELDS = {
        "username": "uid",
        "first_name": "givenName",
        "last_name": "sn",
        "email": "mail",
    }
    

    这个admin用户
    的dn就会变成"uid=admin,ou=people,dc=example,dc=com"不是我们希望的"uid=admin,dc=example,dc=com"因为一般admin是有没有ou这个属性的(我的理解是这样),这个同步成功不了。
    我把site-packages/django_python3_ldap/ldap.py这个文件其中第120行左右的内容改成如下:

    if kwargs:
        password = kwargs.pop("password")
        if username != "cn=admin,dc=node1,dc=com":
            username = import_func(settings.LDAP_AUTH_FORMAT_USERNAME)(kwargs)
    # Make the connection.
    print "***",username # 这样就可以看到他这个模块加工后的dn了,打印出来方便自己检查问题,如果认证不了加上这个基本很多问题都能解决,我还停留在print debug阶段呢,以后要设置断点来debug了O(∩_∩)O~
    

    这样就可以通过这个admin来同步用户信息了。

    结语

    本文我自己实现的认证是通过python-ldap实现的,不过ldap3是更pythonic的模块,我研究了一下,其实完全可以替代python-ldap这个模块的,不过我这个都写完了,ldap3的使用就放在以后吧,我再研究的过程中还在stackoverflow上面问过通过python ldap的模块在不知道用户密码的情况下通过admin给用户重置密码的方法呢,问题链接,最后还是我自己仔细看了官方文档,给解决了,这里面有python-ldap和ldap3的官方文档连接,大家可以看看。我的blog开始有我自己的联系方式啥的,有问题随时问哈。

  • 相关阅读:
    work two year[转]
    知名技术博客内容聚合网站
    VS2010注册码
    某公司的一个题面试题(wfcfan)
    asp.net控件开发基础系列
    .NET (C#) Internals: Delegates1
    可空类型细微见真知!
    C#中操作XML Node节点细节操作
    sql server数据库性能的优化
    字符串精确匹配算法改进的探讨
  • 原文地址:https://www.cnblogs.com/WisWang/p/6820304.html
Copyright © 2011-2022 走看看