1

我正在使用该ldap3模块并尝试创建一个简单的 Web 应用程序来搜索 ldap 服务器中的用户。用户(通常是帮助台人员,进行搜索)必须登录并输入搜索的用户。到目前为止的代码创建/绑定到 ldap 服务器,并且在找到搜索到的用户后,将显示一个不同的页面,显示用户的凭据。到目前为止,一切都很好。

在显示凭据的页面上,有一个搜索框,以便用户可以再次搜索另一个用户。我现在遇到的问题是如何通过 ldap 保持登录状态,以便用户只需要输入搜索到的用户(而不是再次输入他的用户名和密码)。我在想我需要解析conn返回中的对象,但这似乎有点笨拙。这是我的代码:

视图.py

def ldap_authentication(request):             
    if request.POST:
        username = request.POST['username']
        LDAP_MODIFY_PASS = request.POST['password']
        searchFilter = request.POST['searchUser']
        LDAP_AUTH_SEARCH_DN = '{}\\{}'.format(settings.DOMAIN_NAME, username)    

        conn = ldap_connect(request, un=LDAP_AUTH_SEARCH_DN, pw=LDAP_MODIFY_PASS)

        attributes_list_keys = ['mail', 'givenName', 'employeeID', 
        'department', 'telephoneNumber', 'st', 'cn', 'l', 'title']

        conn.search(
                search_base=settings.LDAP_AUTH_SEARCH_BASE,
                search_filter= '(cn={})'.format(searchFilter), 
                search_scope=SUBTREE, 
                attributes = attributes_list_keys
                ) 

        entry = conn.entries[0]

        attributes_split = list(entry._attributes.values())
        attr_keys = []
        attr_values = []
        for i in attributes_split:
            attr_keys.append(i.key)
            attr_values.append(i.value)
        attributes = zip(attr_keys, attr_values)

        return render(request, 'search_page.html', {'attributes':attributes})

    return render(request, 'login.html')

def ldap_connect(request, un=None, pw=None):    
    try:
        # Define the server
        server = Server(settings.LDAP_SERVER, get_info=ALL)
        # Connection and Bind operation 
        conn = Connection(server, user=un, password=pw, \
                        auto_bind=True,check_names=True)
        conn.start_tls() # Session now on a secure channel.
        return conn

    except LDAPBindError as e:
        print ("LDAPBindError, credentials incorrect: {0}".format(e))
        logger.debug("LDAPBindError, credentials incorrect: {0}".format(e))
        sys.exit(1) 

    except LDAPSocketOpenError as e:
        print ("LDAPSocketOpenError, LDAP Server connection error: {0}".format(e))
        logger.debug("LDAPSocketOpenError, LDAP Server connection error: {0}".format(e))
        sys.exit(1)  

def search_ldap_user(request):
    if request.POST:
        searchFilter = request.POST['searchUser']
        print ("searchFilter_POST: {0}".format(searchFilter))
        return render(request, 'login.html')

search_page.html

{% extends "base.html" %}
{% load static %}

{% block content %}
<div class="page-header">
    <h2>LDAP Search Page</h2>
</div>
<p><p>
<div class="tab-content">
        <div class="tab-pane active" id="tab1">
            <table class="table table-striped table-condensed" 
            id="orders_open">
            <thead>
            <tr>
                <th>Attribute in LDAP</th>
                <th>Value</th>
            </tr>
            </thead>
            {% for item1, item2 in attributes %}
            <tr>
                <td>{{ item1 }}</td>
                <td>{{ item2 }}</td>
            </tr>
            {% endfor %}
            </table>
        </div>
</div>
<br><br><br><br>

<form method='post' action="{% url 'searchAnother' %}" class="form-signin">
{% csrf_token %}
    <input type="text" class="form-control" name="searchUser" 
    placeholder="Search User" required=""/>
    <button type="submit">Search</button>
</form> 
<form method='post' action="" class="form-signin">{% csrf_token %}
        <br>
        <a href="{% url 'logout' %}" class="btn btn-lg btn-danger btn-
block">LogOut</a>
</form>

{% endblock content %}

登录.html

{% extends "base.html" %}
{% load static %}

{% block content %}
<div class="page-header">
        <h2>Welcome to LDAP Search. Please enter your credentials.</h2>
</div>

<div class="wrapper">
    <form method='post' action="" class="form-signin">{% csrf_token %}
        <h3 class="form-signin-heading">Please login</h3>
        <input type="text" class="form-control" name="username" 
        placeholder="Username" required="" autofocus=""/>
        <br>
        <input type="password" class="form-control" name="password" 
        placeholder="Password" required=""/>
        <br>
        <input type="text" class="form-control" name="searchUser" 
        placeholder="Search User" required=""/>
        <br>
        <button class="btn btn-lg btn-primary btn-block" type="submit">Login</button>
    </form>
</div>

{% endblock content %}

我认为问题在于以某种方式将search_ldap_usermyviews.py中的函数与search_page.html通过 conn 对象联系起来,但似乎不清楚我该如何做到这一点。有没有人使用 ldap 进行身份验证的类似经验?

更新

所以我切换到django_python3_ldap图书馆,有以下内容:

设置.py

DOMAIN_NAME = 'OurDomain'
LDAP_AUTH_URL = 'ldap://10.254.9.31:389'                    
LDAP_AUTH_USE_TLS = False                                   
LDAP_AUTH_SEARCH_BASE = 'ou=company-Konzern, dc=ourdomain, dc=de' 
LDAP_AUTH_OBJECT_CLASS = 'inetOrgPerson'                    

LDAP_AUTH_USER_FIELDS = {
    "username": "cn",
    "first_name": "givenName",
    "last_name": "sn",
    "email": "mail",
}

# More info: https://github.com/etianen/django-python3-ldap
#LDAP_AUTH_USER_LOOKUP_FIELDS = ("username",)
LDAP_AUTH_USER_LOOKUP_FIELDS = ("cn",)
LDAP_AUTH_CLEAN_USER_DATA = "django_python3_ldap.utils.clean_user_data"
LDAP_AUTH_SYNC_USER_RELATIONS = "django_python3_ldap.utils.sync_user_relations"
LDAP_AUTH_FORMAT_SEARCH_FILTERS = "django_python3_ldap.utils.format_search_filters"
LDAP_AUTH_FORMAT_USERNAME = "django_python3_ldap.utils.format_username_openldap"
LDAP_AUTH_ACTIVE_DIRECTORY_DOMAIN = 'OurDomain'

#LDAP_AUTH_CONNECTION_USERNAME = 'e123456'
LDAP_AUTH_CONNECTION_USERNAME = 'OurDomain\e123456'
LDAP_AUTH_CONNECTION_PASSWORD = 'abcdefghi'

LDAP_AUTH_CONNECT_TIMEOUT = None
LDAP_AUTH_RECEIVE_TIMEOUT = None

AUTHENTICATION_BACKENDS = (  
    'django_python3_ldap.auth.LDAPBackend',
    'django.contrib.auth.backends.ModelBackend',
)

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_python3_ldap'
]

视图.py

def ldap_login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        print ("username: {0}".format(username))
        print ("password: {0}".format(password))
        ldap_auth_search_dn = '{}\\{}'.format(settings.DOMAIN_NAME, username)    
        print ("ldap_auth_search_dn: {0}".format(ldap_auth_search_dn))

        user = authenticate(username=username, password=password)
        #user = authenticate(username=ldap_auth_search_dn, password=password)
        print ("user: {0}".format(user))
        if user and user.is_active:
            print ("user.is_active!!")
            login(request, user, backend='django_python3_ldap.auth.LDAPBackend')

    return render(request, 'login_ldap.html')

正如您从注释掉的行中看到的那样,我在 settings.py 中尝试了各种配置排列,但仍有一些我不清楚的问题:

  1. 这在 settings.py: 中是强制性的LDAP_AUTH_OBJECT_CLASS吗?
  2. 哪个是正确LDAP_AUTH_USER_LOOKUP_FIELDS使用?
  3. 与 2 相同,但对于LDAP_AUTH_CONNECTION_USERNAME(这是否应该包括域)?

使用命令时抛出以下错误消息

python ./manage.py ldap_sync_users

错误:

CommandError: Could not connect to LDAP server

当我不使用ldap_sync_users命令而只是运行服务器时,似乎没有连接,因为userprint 语句中的返回为None. 我知道连接有效的凭据,因为我之前使用该ldap3库的代码有效。我唯一能想到的是LDAP_AUTH_SEARCH_BASE两个库之间的不一样。

4

1 回答 1

0

使用django-python3-ldapwhich 是基于ldap3我使用 repo 中描述的基本设置进行身份验证的:

from django.contrib.auth import authenticate, login

def ldap_login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        user = authenticate(username=username, password=password)
        # Test return values
        if user and user.is_active:
            login(request, user, backend='django_python3_ldap.auth.LDAPBackend')

            return JsonResponse({'success': 'YES'})
        return JsonResponse({'success': 'NO'})

这实际上与正常的身份验证过程没有什么不同。

于 2017-10-20T07:01:24.927 回答