了解Django-LDAP身份验证

39

我是Django的新手,被分配实现使用LDAP作为后端的用户认证系统的任务。我猜测文档假设最终开发人员有足够的Django经验来理解和实现这样一个系统。但我不明白如何使用LDAP来实现一个简单的Django应用程序。到目前为止,这是我已经了解到的内容:

仅发布对文件的更改:

settings.py
....
import ldap
from django_auth_ldap.config import LDAPSearch

AUTH_LDAP_SERVER_URI = "ldap://<my url>" 
AUTHENTICATION_BACKENDS = ('django_auth_ldap.backend.LDAPBackend')

AUTH_LDAP_CONNECTION_OPTIONS = { 
    ldap.OPT_REFERRALS: 0
}

MIDDLEWARE_CLASSES = ( 
     ....
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    ...
)

INSTALLED_APPS = ( 
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    ....
)

auth.html

<html>
    <head>
        <title>Login</title>
    </head>
    <body>
        {{state}}
        <form action="" method="post"> {% csrf_token %}
            Email address: <input type="text" name="email" value="{{ email }}" />
            Password: <input type="password" name="password" value="" />
            <input type="submit" value="Log in" />
        </form>
    </body>
</html>

models.py:

??

views.py:

from django.shortcuts import render_to_response
from django.contrib.auth import authenticate, login
from django.template import RequestContext


def login_user(request):

    username = password = ""
    state = ""

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

        print username, password

        user = authenticate(username=username, password=password)
        if user is not None:
            login(request, user)
            state = "Valid account"
        else:
            state = "Inactive account"
    return render_to_response('auth_user/auth.html', RequestContext(request, {'state': state, 'username': username}))
我不明白的是什么?
1> 我十分确定需要在views.py中实现一个函数来获取emailpasswordPOST值并进行验证,例如:[SO]。文档说明要么实现Search/Bind,要么实现Direct Bind。为什么?如果views.py包含了实际的身份验证代码,那么文档中指定的代码是在做什么呢?
2> 如果views.py已经执行了实际的身份验证,那么为什么我们还需要文档中指定的那个变量?
3> 作者在这个库中做得非常好,但是文档没有提供如何使用LDAP实现整个身份验证系统的简单示例。如果有这样的资源,能否请任何人指出?理解需要添加/修改的文件以实现这样的系统并不容易。

您的文档链接需要更新为 https://django-auth-ldap.readthedocs.io/en/latest/。 - Shadi
2个回答

35

这个页面可能有你想要的内容:https://pypi.python.org/pypi/django-auth-ldap,它涉及到LDAP后端。你很幸运,因为已经存在一个这样的后端,所以你不必自己编写认证后端 :-)

基本上,django.contrib.auth.models 已经有一个 User 对象,包含了关于用户的所有信息,所以你不需要创建新的 models.py。

你只需要在你的 views.py 中,在登录函数中进行身份验证,使用:

from django.contrib.auth import authenticate, login
user = authenticate(username=request.REQUEST.get('email'), password=request.REQUEST.get('password'))
# handle error cases, inactive users, ...
login(request, user)
如果用户为None,则表示身份验证失败。如果不是,你可以探索这个对象来查看后端为你提供了什么。
然后,如果你想将首选项链接到此应用程序但不是LDAP的一部分,请选择使用User作为foreignKey创建另一个模型。
在这种情况下,你需要:
Models.py
根据你的应用程序重要性定义数据的定义。你将从LDAP中提取用户数据,并将其填充到此模型以及其他与用户相关的首选项中:
from django.contrib.auth.models import User    

class Profile(models.Model):
    """User profile.  Contains some basic configurable settings"""
    user = models.ForeignKey(User, unique=True)
    phone_number = models.CharField(max_length=256, blank=True, default='')
    ...

Views.py

  • 在登录函数中,如果 request.method == 'POST',则使用从 authenticate 得到的用户信息进行 get_or_create 操作以获取用户配置文件。

profile, profile_is_new = Profile.objects.get_or_create(user=user)

感谢您的反馈。虽然我可以使用django-auth-ldap库从命令行验证凭据,但在Django应用程序中却失败了。我猜测配置细节可能没有被捕获,或者authenticate并没有真正针对LDAP服务器进行身份验证。您认为我在settings.py中漏掉了什么吗? - name_masked
我实在说不准,因为我从未使用过LDAP Django auth。但是,在我看来,你的设置看起来很好。也许你只想将django.contrib.auth.backends.ModelBackend作为AUTHENTICATION_BACKENDS元组的第二个成员添加进去,但我不认为这对你的特定问题会有太大帮助。抱歉。 - Ptah
2
我在上面的代码中忘记了一些重要的东西,涉及到视图...在身份验证之后,使用django.contrib.auth.login(request, user)告诉Django将用户保存到会话中。已更新我的答案。 - Ptah
您的文档链接需要更新为https://django-auth-ldap.readthedocs.io/en/latest/。 - Shadi

7

django-auth-ldap文档确实是为熟悉Django和LDAP的开发人员编写的。如果您从零开始,我建议逐步进行:

  1. Django教程
  2. Django认证
  3. 如果您还不熟悉LDAP,请参考某种LDAP教程。
  4. django-auth-ldap

谢谢您的回复。我猜您是这个库的作者?我的问题意图在于了解如何在Django项目中使用AUTH_LDAP_变量进行身份验证以及其他更改。虽然我创建了一个简单的Django应用程序,其中包含一个电子邮件和密码表单,使用conn = ldap.initialize("<url>")检查身份验证,然后使用UI中输入的电子邮件和密码执行conn.bind_s(email, password),这很好用。但是,这并不清楚,我想这也是人们询问如何使其工作的原因。 - name_masked
1
搞定了,发现 AUTH_LDAP_USER_DN_TEMPLATE 应该设置为输入的确切电子邮件地址,无需包含整个 dn 值,即只需 AUTH_LDAP_USER_DN_TEMPLATE=%(user)s - name_masked
很高兴它正在工作。LDAP配置可能会有很大的差异,因此有些问题只有您或LDAP管理员才能回答。 - psagers
1
我明白。但是,我仍然觉得文档缺少最常见情况的示例。例如:1>使用django-auth-ldap使用电子邮件和密码对LDAP进行身份验证。2>填充其他字段(如is_staff)。我如何使用dispatcher来填充这些字段? - name_masked
您的文档链接需要更新为 https://django-auth-ldap.readthedocs.io/en/latest/。 - Shadi
3
那么解决方案就是自己去想吗? - rfportilla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接