Django: аутентификация удаленного пользователя LDAP - простой пример? - PullRequest
14 голосов
/ 25 февраля 2011

Я использую django_auth_ldap - у нас есть существующая база данных пользователей и внешняя система LDAP, которая делит имена пользователей с базой данных пользователей, которая у меня уже есть.

Я мог бы сделать простой пример того, как

  • получить локальное имя пользователя (они вошли в систему Windows LDAP - могу ли я как-нибудь получить это имя пользователя из браузера?)
  • аутентификация на удаленном сервере LDAP Windows
  • используйте это в шаблоне Django (было бы просто отображать имя)

Может ли кто-нибудь предоставить (надеюсь) несколько строк кода для простого примера того, как это сделать?

спасибо!

Ответы [ 3 ]

1 голос
/ 22 сентября 2011

В вашем файле настроек Python добавьте строку

AUTHENTICATION_BACKENDS = (
    'django_auth_ldap.backend.ActiveDirectoryGroupMembershipSSLBackend',
    'django.contrib.auth.backends.ModelBackend'
)

Вот мой код, просто замените его своей информацией.Сохраните этот файл как backend.py Поместите файл в папку с именем django_auth_ldap.Убедитесь, что в папке есть файл __init.py.

import ldap;

from django.contrib.auth.models import User, Group

class ActiveDirectoryGroupMembershipSSLBackend:
    #Required parameters
    AD_DNS_NAME ='your remote ldap server location';
    AD_LDAP_PORT = 636
    AD_LDAP_URL = 'ldaps://%s' % AD_DNS_NAME;
    AD_SEARCH_DN = 'dc=bbc,dc=ad,dc=bcc,dc=net'; # this is your search dn
    AD_NT4_DOMAIN = 'bbc.ad.bbc.net'; #its your ad domain
    AD_SEARCH_FIELDS = ['mail','givenName','sn','sAMAccountName','memberOf'];
    AD_MEMBERSHIP_REQ = ['Group_Required','Alternative_Group'];
    AD_CERT_FILE = "C:/player/Python/Application/cert/mycert.cer";
AD_DEBUG = False;
AD_DEBUG_FILE ='';

def authenticate(self,username=None,password=None):
    try:
        if len(password) == 0:
            return None
        ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND)
        ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 2)
        l = ldap.initialize(self.AD_LDAP_URL)
        l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
        binddn = "%s@%s" % (username,self.AD_NT4_DOMAIN)
        l.simple_bind_s(binddn,password)
        l.unbind_s()
        return self.get_or_create_user(username,password)

    except ImportError:
        pass
    except ldap.INVALID_CREDENTIALS:
        pass

def get_or_create_user(self, username, password):
    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:

        try:
        # debug info
            debug=0
            if len(self.AD_DEBUG_FILE) > 0:
                if self.AD_DEBUG:
                    debug = open(self.AD_DEBUG_FILE,'w')
                    print >>debug, "create user %s" % username

            ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,self.AD_CERT_FILE)
            ldap.set_option(ldap.OPT_REFERRALS,0) # DO NOT TURN THIS OFF OR SEARCH WON'T WORK!      
            # initialize
            if debug:
                print >>debug, 'ldap.initialize...'
            l = ldap.initialize(self.AD_LDAP_URL)
            l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)

            # bind
            if debug:
                print >>debug, 'bind...'
            binddn = "%s@%s" % (username,self.AD_NT4_DOMAIN)
            l.bind_s(binddn,password)

            # search
            if debug:
                print >>debug, 'search...'
            result = l.search_ext_s(self.AD_SEARCH_DN,ldap.SCOPE_SUBTREE,"sAMAccountName=%s" % username,self.AD_SEARCH_FIELDS)[0][1]
            if debug:
                print >>debug, result

            # Validate that they are a member of review board group
            if result.has_key('memberOf'):
                membership = result['memberOf']
            else:
                membership = None
            if debug:
                print >>debug, "required:%s" % self.AD_MEMBERSHIP_REQ
            bValid=0
            for req_group in self.AD_MEMBERSHIP_REQ:
                if debug:
                    print >>debug, "Check for %s group..." % req_group
                for group in membership:
                    group_str="CN=%s," % req_group
                    if group.find(group_str) >= 0:
                        if debug:
                            print >>debug, "User authorized: group_str membership found!"
                        bValid=1
                        break
            if bValid == 0:
                if debug:
                    print >>debug, "User not authorized, correct group membership not found!"
                return None

            # get email
            if result.has_key('mail'):
                mail = result['mail'][0]
            else:
                mail = None
            if debug:
                print >>debug, "mail=%s" % mail
            # get surname
            if result.has_key('sn'):
                last_name = result['sn'][0]
            else:
                last_name = None
            if debug:
                print >>debug, "sn=%s" % last_name

            # get display name
            if result.has_key('givenName'):
                first_name = result['givenName'][0]
            else:
                first_name = None
            if debug:
                print >>debug, "first_name=%s" % first_name

            l.unbind_s()

            user = User(username=username,first_name=first_name,last_name=last_name,email=mail)

        except Exception, e:
            if debug:
                print >>debug, "exception caught!"
                print >>debug, e
            return None

        user.is_staff = False
        user.is_superuser = False
        user.set_password('ldap authenticated')
        user.save()

        # add user to default group
        group=Group.objects.get(pk=1)
        if debug:
            print >>debug, group
        if debug:
            print >>debug, "add %s to group %s" % (username,group)
        user.groups.add(group)
        user.save()
        if debug:
            print >>debug, "successful group add"

        if debug:
            debug.close()

    return user

def get_user(self, user_id):
    try:
        return User.objects.get(pk=user_id)
    except User.DoesNotExist:
        return None
0 голосов
/ 30 апреля 2015

Во-первых, я бы предложил попросить пользователя предоставить sAMAccountName (которое является точным именем входа в Windows и обычно «firstName.lastName», также лучше, если у пользователя несколько слов в имени), а не просто использовать имя пользователя cn (' имя Фамилия').

Ниже приведен мой полный код LDAPUserAuthBackend, и он добавлен в AUTHENTICATION_BACKENDS

from django.contrib.auth.backends import RemoteUserBackend
from django.contrib.auth.models import User, Permission
from django.conf import settings
import ldap
import re

import logging

log = logging.getLogger(__name__)
INTERNAL_USER = None


class LDAPUserAuthBackend(RemoteUserBackend):

    create_unknown_user = False

    def authenticate(self, username=None, password=None, **kwargs):
        # if username or password is not given, then skip
        if not username or not password:
            return None

        try:
            # initialize connection to ActiveDirectory  the property contains ldap url like ldap://hostname:389
            connect = ldap.initialize(settings.AUTH_LDAP_SERVER_URL)

            # if user just provide account name portion 'fistName.lastName' on username
            # then use your company default domain
            if '\\' not in username:
                connect.simple_bind_s(username + '@myCompanyDomain.com', password)
                base_dn = 'cn=users,dc=myCompanyDomain,dc=com'
                search_filter = '(&(objectClass=user)(sAMAccountName=' + username + '))'
            else:
                # if user provides domain info in username like 'myCompanyDomain\firstName.lastName'
                domain,  account_name = username.split('\\')
                connect.simple_bind_s('{user_name}@{domain_name}.com'.format(user_name=account_name, domain_name=domain), password)
                base_dn = 'cn=users,dc={domain_name},dc=com,'.format(domain_name=domain)
                search_filter = '(&(objectClass=user)(sAMAccountName=' + account_name + '))'
                username = account_name
            result = connect.search_s(base_dn, ldap.SCOPE_SUBTREE, search_filter, ['memberOf'])
            log.debug(result)

            # if search result is found, result will be [(user_dn,{'memberOf':['group cn'...]}]
            if result:
                result_user_dn, result_dict = result[0]
                groups = ','.join(result_dict.get('memberOf')).lower()
                # check member is belong to the group
                if result_user_dn:
                    if settings.STAFF_USER_GROUP.lower() in groups or \
                       settings.ADMIN_USER_GROUP.lower() in groups:
                        user, created = User.objects.get_or_create(username=username)
                        first_name, last_name = re.split('\.', username)
                        user.first_name = first_name
                        user.last_name = last_name
                        user.is_active = True
                        user.is_staff = True
                        if settings.ADMIN_USER_GROUP.lower() in groups:
                            user.is_superuser = True
                        global INTERNAL_USER
                        INTERNAL_USER = user
                        return user
            log.info('fail to authorize user, username: {}'.format(username))
            return None
        except ldap.LDAPError as e:
            log.warning('authentication error, detail: {}'.format(str(e)))
            return None
        finally:
            connect.unbind_s()

    def get_user(self, user_id):
        # don't want to go back to database.
        # once auth via LDAP successful, that is the user
        # because of the user_id is for user passed auth via this backend
        global INTERNAL_USER
        return INTERNAL_USER
0 голосов
/ 29 марта 2011

Пытаетесь ли вы найти решение для единого входа, подходящее для пользователей MS Windows?

Тогда вы найдете все необходимые подсказки в http://docs.djangoproject.com/en/dev/howto/auth-remote-user/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...