首页 文章

如何通过直接绑定django与多个ldap服务器,多个域来验证用户

提问于
浏览
0

我是Python和django的新蜜蜂 . 我搜索了很多但是找不到令人满意的解决方案来解决我的下面情况 .

该公司为不同的域提供了不同的ldap服务器(我认为是微软) . 用户登录表单包含用户名,密码和域名 . 我需要根据他的域名选择来验证服务器的凭据 . 我知道哪个服务器用于给定的域 . 我没有管理员登录名和密码来进行ldap搜索 . 所以我宁愿使用ldap direct bind .

鉴于这种情况,我想问一下“如何使用ldap direct bind对多个具有不同域的ldap服务器的用户进行身份验证” . 任何帮助,将不胜感激 .

我正在努力寻找解决方案 . 如果我得到它,我会发布它 .

2 回答

  • 0

    一个选项可能是忽略域,使用django-auth-ldap的multiple-backend功能,让它尝试每个,直到成功为止 . 当然,那是相当不满意的 . 使用一些自定义代码,您应该能够正确执行此操作:

    from django_auth_ldap import LDAPBackend
    
    
    class LDAPDomainBackend(LDAPBackend):
        domain = None
    
        def authenticate(self, username=None, password=None, domain=None):
            if None in [username, password, domain]:
                return None
    
            if domain == self.domain:
                user = super(LDAPDomainBackend, self).authenticate(username=username, password=password)
            else:
                user = None
    
            return user
    
    class DomainFooBackend(LDAPDomainBackend):
        settings_prefix = 'AUTH_LDAP_FOO_'
        domain = 'foo'
    
    
    class DomainBarBackend(LDAPDomainBackend):
        settings_prefix = 'AUTH_LDAP_BAR_'
        domain = 'bar'
    

    settings.py:

    AUTHENTICATION_BACKENDS = [
        'path.to.DomainFooBackend',
        'path.to.DomainBarBackend',
    ]
    
    
    AUTH_LDAP_FOO_SERVER_URI = 'ldap://foo.example.com'
    AUTH_LDAP_FOO_USER_DN_TEMPLATE = '...'
    
    AUTH_LDAP_BAR_SERVER_URI = 'ldap://bar.example.com'
    AUTH_LDAP_BAR_USER_DN_TEMPLATE = '...'
    
  • 0

    以下是我特定问题的解决方案 . 对于有类似我的问题的人会有用 .

    settings.py

    AUTHENTICATION_BACKENDS = (
    #'django.contrib.auth.backends.ModelBackend',
    'rango.auth.SettingsBackend',
    'rango.auth.CustomLdapBackend',
    
    )
    
    ADMIN_CREDENTIALS = {
        'admin':'pbkdf2_sha256$12000$btzDXMsGghKq$Bv1GasiWFSJXQUn7J4gHCzJVubm9ZAHfiMaVNdblo9Y=',
    }
    AUTH_LDAP_SERVERS = {
        'DOMAIN-1':{'URI':'123.4.56.78', 'DN':'dc=bla,dc=bla,dc=com',},
        'DOMAIN-2':{'URI':'123.4.56.79', 'DN':'dc=blue,dc=blue,dc=com',},
        'DOMAIN-3':{'URI':'123.4.56.77', 'DN':'dc=black,dc=vblack,dc=com',},
    }
    

    富/ models.py

    from django.db import models
    from django.contrib.auth.models import User
    
    class UserProfile(models.Model):
        user = models.OneToOneField(User)
    
        domain = models.CharField(max_length=30)
    
        def __unicode__(self):
            return self.user.username
    #
    

    富/ auth.py

    from django.contrib.auth.models import User, check_password
    from rango.models import UserProfile
    import ldap
    from django.conf import settings
    from django.contrib.auth.backends import ModelBackend
    #
    
    
    class Backend(ModelBackend):
        def authenticate(self, username=None, password=None, domain=None):
            pass
        def get_user(self, user_id):
            try:
                return User.objects.get(pk=user_id)
            except User.DoesNotExist:
                return None
    
        def get_user_by_username(self,username):
            try:
                return User.objects.get(username=username)
            except:
                return None
    #
    
    
    class LdapBackend(Backend):
        def _get_ldap_user_by_username(self, conn, username, dn):
            try:
                search_scope = ldap.SCOPE_SUBTREE
                retrieve_attributes = None
                search_filter = "samaccountname="+username
                result_id = conn.search(dn,search_scope,search_filter,retrieve_attributes)
                result_set = []
                ldap_user = {}
                while 1:
                    result_type, result_data = conn.result(result_id,0)
                    if (result_data ==[]):
                        break
                    else:
                        if result_type == ldap.RES_SEARCH_ENTRY:
                            result_set.append(result_data)
    
                ldap_user = result_set[0][0][1]
                return ldap_user
            except:
                return {}
    #
    
    
    class CustomLdapBackend(LdapBackend):
        def authenticate(self, username=None, password=None, domain=None):
            try:
                credentials = [username, password, domain]
                if (None in credentials) or ('' in credentials):
                    return None
    
                if domain not in settings.AUTH_LDAP_SERVERS:
                    return None
    
                ldap.set_option( ldap.OPT_REFERRALS,0 )
                try:
                    conn = ldap.initialize('ldap://'+ settings.AUTH_LDAP_SERVERS[domain]['URI'])
                    conn.simple_bind_s( username + '@' + domain, password )
                except:
                    conn.unbind_s()
                    return None
    
                user = self.get_user_by_username( username=username )
    
                if user is None:
                    user = User(username=username, password='')
                    user.save()
                    user = self.get_user_by_username(username)
                    ldap_user = self._get_ldap_user_by_username(conn=conn, 
                            username=username,dn= settings.AUTH_LDAP_SERVERS[domain]['DN']
                        )
    
                    if ldap_user is not None:
                        try:
                            user.first_name = ldap_user['givenName'][0]
                        except:
                            pass
                        try:
                            user.last_name = ldap_user['sn'][0]
                        except:
                            pass
                        try:
                            user.email = ldap_user['mail'][0]
                        except:
                            pass
                    user.save()
                    user = self.get_user_by_username(username=username)
                    user_profile = UserProfile(user=user, domain=domain)
                    user_profile.save()
                    user = self.get_user_by_username(username=username)
                conn.unbind_s()
    
                if str(user.userprofile.domain) != domain:
                    return None
    
                user.set_password(password)
                user.save()
                return user
            except:
                return None
    #
    
    
    class SettingsBackend(Backend):
        def authenticate(self, username=None, password=None, domain=None ):
    
            try:
                if username not in settings.ADMIN_CREDENTIALS :
                    return None
    
                if check_password(password, settings.ADMIN_CREDENTIALS[username]):
                    user = self.get_user_by_username(username = username)
                    if user is None:
                        # create one
                        user = User(username=username, password= settings.ADMIN_CREDENTIALS[username])
                        user.is_staff = True
                        user.is_superuser = True
                        user.save()
                    return user
                return None
            except:
                return None
    #
    

    /foo/login.html

    <!DOCTYPE html>
    <html>
        <head><title>foo</title></head>
    
        <body>
            <h1>Login to foo</h1>
    
            <form id="login_form" method="post" action="/foo/login/" >
            {% csrf_token %}
            Username: <input type="text" name="username" value="" size="50" />
            
    Password: <input type="password" name="password" value="" size="50" />
    Domain: <select id="domain" name="domain"> <option selected value="DOMAIN-1">DOMAIN-1</option> <option value="DOMAIN-2">DOMAIN-2</option> <option value="DOMAIN-3">DOMAIN-3</option> </select>
    <input type="submit" value="submit"/> </form> </body> </html>

    富/ views.py

    def user_login(request):
        context = RequestContext(request)
    
        if request.method == 'POST':
            username = request.POST['username']
            password = request.POST['password']
            domain = request.POST.get('domain', None )
            user = authenticate( username=username, password=password, domain=domain )
    
            if user:
                if user.is_active:
                    print request.user.id
                    login(request, user)
                    return HttpResponseRedirect('/foo/')
                else:
                    return HttpResponse("Your fooaccount is disabled.")
            else:
                print "Invalid login details: {0}, {1}".format(username, password)
                return HttpResponse("Invalid login details supplied.")
        else:
            return render_to_response('foo/login.html', {}, context)
    #
    

相关问题