Django Auth LDAP - прямое связывание с использованием sAMAccountName

Существует два способа аутентификации пользователя с использованием Django Auth LDAP.

  1. Поиск / Связать и
  2. Прямое связывание.

Первый включает в себя подключение к серверу LDAP анонимно или с фиксированной учетной записью и поиск отличительного имени аутентифицирующего пользователя. Затем мы можем попытаться снова связать с паролем пользователя.

Второй метод заключается в получении DN пользователя из его имени пользователя и попытке привязки как пользователя напрямую.

Я хочу иметь возможность делать прямую привязку, используя идентификатор пользователя (sAMAccountName) и пароль пользователя, который пытается получить доступ к приложению. Пожалуйста, дайте мне знать, если есть способ достичь этого? На данный момент я не могу заставить это работать из-за проблемы, описанной ниже.

В моем случае DN пользователей в LDAP имеет следующий формат

**'CN=Steven Jones,OU=Users,OU=Central,OU=US,DC=client,DC=corp'**

Это в основном переводится как "CN=FirstName LastName,OU= Пользователи, OU = Центральный, OU = США,DC= клиент,DC= корпорация"

Это мешает мне использовать Direct Bind, так как sAMAccountName пользователя - sjones, и это параметр, который соответствует имени пользователя (%user), и я не могу найти способ создать правильный AUTH_LDAP_USER_DN_TEMPLATE для получения DN пользователя с помощью.

Из-за описанной выше проблемы я сейчас использую Search/Bind, но для этого необходимо, чтобы в AUTH_LDAP_BIND_DN и AUTH_LDAP_BIND_PASSWORD были указаны фиксированные учетные данные пользователя.

Вот моя текущая конфигурация settings.py

AUTH_LDAP_SERVER_URI = "ldap://10.5.120.161:389"
AUTH_LDAP_BIND_DN='CN=Steven Jones,OU=Users,OU=Central,OU=US,DC=client,DC=corp'
AUTH_LDAP_BIND_PASSWORD='fga.1234'
#AUTH_LDAP_USER_DN_TEMPLATE = 'CN=%(user)s,OU=Appl Groups,OU=Central,OU=US,DC=client,DC=corp'
AUTH_LDAP_USER_SEARCH = LDAPSearchUnion(
    LDAPSearch("OU=Users, OU=Central,OU=US,DC=client,DC=corp",ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)"),
    LDAPSearch("OU=Users,OU=Regional,OU=Locales,OU=US,DC=client,DC=corp",ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)"),
    )
AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", "last_name": "sn","email":"mail"}
AUTH_LDAP_GROUP_SEARCH = LDAPSearch("CN=GG_BusinessApp_US,OU=Appl Groups,OU=Central,OU=US,DC=client,DC=corp",ldap.SCOPE_SUBTREE, "(objectClass=groupOfNames)")
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()
AUTH_LDAP_REQUIRE_GROUP = 'CN=GG_BusinessApp_US,OU=Appl Groups,OU=Central,OU=US,DC=client,DC=corp'

С нетерпением ждем некоторых указаний от замечательных людей здесь.

6 ответов

Решение

Я была такая же проблема.

Я столкнулся с: https://bitbucket.org/psagers/django-auth-ldap/issue/21/cant-bind-and-search-on-activedirectory

Автор предложил способ изменения файлов библиотеки для django-auth-ldap, чтобы он мог выполнять прямую привязку.

Дело дошло до изменения /django_auth_ldap/backend.py, чтобы включить две строки вокруг строки 364:

if sticky and ldap_settings.AUTH_LDAP_USER_SEARCH:
    self._search_for_user_dn()[/code]

Мне удалось заставить это работать на моем локальном компьютере, на котором работал Arch Linux 3.9.8-1-ARCH, но я не смог скопировать его на dev-сервер под управлением Ubuntu 13.04.

Надеюсь, это поможет.

(На самом деле это комментарий к ответу @amethystdragon, но это набор кода, поэтому публикация в виде отдельного ответа.) Кажется, проблема все еще существует с django_auth_ldap 1.2.5. Вот обновленный патч. Если вы не хотите или не можете изменить исходный код, возможна мартышка-патчинг. Просто поместите этот код, например, в. конец чего-либо settings.py, (И да, я знаю, что исправление обезьян ужасно.)

import ldap
from django_auth_ldap import backend

def monkey(self, password):
  """
  Binds to the LDAP server with the user's DN and password. Raises
  AuthenticationFailed on failure.
  """
  if self.dn is None:
    raise self.AuthenticationFailed("failed to map the username to a DN.")

  try:
    sticky = self.settings.BIND_AS_AUTHENTICATING_USER

    self._bind_as(self.dn, password, sticky=sticky)

    #### The fix -->
    if sticky and self.settings.USER_SEARCH:
      self._search_for_user_dn()
    #### <-- The fix

  except ldap.INVALID_CREDENTIALS:
    raise self.AuthenticationFailed("user DN/password rejected by LDAP server.")

backend._LDAPUser._authenticate_user_dn = monkey

У меня также была эта проблема, но я не хотел изменять settings.py файл. Решением для меня было закомментировать строку "AUTH_LDAP_USER_DN_TEMPLATE = "uid=%(user)s,ou= путь, dc = to, dc = домен "". Я также добавил NestedActiveDirectoryGroupType как часть моего устранения неполадок. Не уверен, если это необходимо, но он работает сейчас, поэтому я оставляю это. Вот мой ldap_config.py файл.

import ldap

# Server URI
AUTH_LDAP_SERVER_URI = "ldap://urlForLdap"

# The following may be needed if you are binding to Active Directory.
AUTH_LDAP_CONNECTION_OPTIONS = {
       # ldap.OPT_DEBUG_LEVEL: 1,
    ldap.OPT_REFERRALS: 0
}

# Set the DN and password for the NetBox service account.
AUTH_LDAP_BIND_DN = "CN=Netbox,OU=xxx,DC=xxx,DC=xxx"
AUTH_LDAP_BIND_PASSWORD = "password"

# Include this setting if you want to ignore certificate errors. This might be needed to accept a self-signed cert.
# Note that this is a NetBox-specific setting which sets:
#     ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
LDAP_IGNORE_CERT_ERRORS = True

from django_auth_ldap.config import LDAPSearch, NestedActiveDirectoryGroupType

# This search matches users with the sAMAccountName equal to the provided username. This is required if the user's
# username is not in their DN (Active Directory).
AUTH_LDAP_USER_SEARCH = LDAPSearch("OU=xxx,DC=xxx,DC=xxx",
                                    ldap.SCOPE_SUBTREE,
                                    "(sAMAccountName=%(user)s)")

# If a user's DN is producible from their username, we don't need to search.
# AUTH_LDAP_USER_DN_TEMPLATE = "uid=%(user)s,ou=users,dc=corp,dc=loc"

# You can map user attributes to Django attributes as so.
AUTH_LDAP_USER_ATTR_MAP = {
    "first_name": "givenName",
    "last_name": "sn",
    "email": "mail"
}

from django_auth_ldap.config import LDAPSearch, GroupOfNamesType, NestedActiveDirectoryGroupType

# This search ought to return all groups to which the user belongs. django_auth_ldap uses this to determine group
# heirarchy.
AUTH_LDAP_GROUP_SEARCH = LDAPSearch("dc=xxx,dc=xxx", ldap.SCOPE_SUBTREE,
                                    "(objectClass=group)")
AUTH_LDAP_GROUP_TYPE = NestedActiveDirectoryGroupType()

# Define a group required to login.
AUTH_LDAP_REQUIRE_GROUP = "CN=NetBox_Users,OU=NetBox,OU=xxx,DC=xxx,DC=xxx"

# Define special user types using groups. Exercise great caution when assigning superuser status.
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
    "is_active": "CN=NetBox_Active,OU=NetBox,OU=xxx,DC=xxx,DC=xxx",
    "is_staff": "CN=NetBox_Staff,OU=NetBox,OU=xxx,DC=xxx,DC=xxx",
    "is_superuser": "CN=NetBox_Superuser,OU=NetBox,OU=xxx,DC=xxx,DC=xxx"
}

# For more granular permissions, we can map LDAP groups to Django groups.
AUTH_LDAP_FIND_GROUP_PERMS = True

# Cache groups for one hour to reduce LDAP traffic
AUTH_LDAP_CACHE_GROUPS = True
AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600

Я думаю, что использование прямого связывания (как показано ниже) с последующей передачей общего имени в интерфейсе входа в систему сделает работу, и, следовательно, нет необходимости устанавливать статические учетные данные для аутентификации.

AUTH_LDAP_USER_DN_TEMPLATE = "CN=%(user)s,OU=users,OU=OR-TN,DC=OrangeTunisie,DC=intra"

У меня также была эта проблема, когда на старом сервере ldap был dn, который начинался с uid, но DN нового начинался с CN ("Стивен Джонс"). Я использовал эту конфигурацию (которая решила это для меня) в setting.py:

AUTH_LDAP_BIND_DN = 'CN=adreader,CN=Users,DC=xxx, DC=yyy'

from django_auth_ldap.config import LDAPSearch
import ldap
AUTH_LDAP_USER_SEARCH = LDAPSearch(base_dn='ou=People, ou=xxx, dc=yyy, dc=zzz, 
  scope=ldap.SCOPE_SUBTREE, filterstr='(sAMAccountName=%(user)s)')

Приведенные выше ответы не сработали для меня, но я нашел способ заставить его работать. Хитрость заключается в использовании sAMAAcountname в сочетании с доменным именем для привязки.

  1. измените DN шаблона, чтобы он использовал формат [email protected] .
  2. используйте модифицированный патч обезьяны для поиска и сохранения CN реального пользователя (self._user_dn).

Настройки:

      AUTH_LDAP_BIND_AS_AUTHENTICATING_USER = True
AUTH_LDAP_USER_DN_TEMPLATE = '%(user)s@example.com'

Пластырь:

      import ldap
from django_auth_ldap import backend

def monkey(self, password):
    """
    Binds to the LDAP server with the user's DN and password. Raises
    AuthenticationFailed on failure.
    """
    if self.dn is None:
        raise self.AuthenticationFailed("failed to map the username to a DN.")

    try:
        sticky = self.settings.BIND_AS_AUTHENTICATING_USER

    self._bind_as(self.dn, password, sticky=sticky)

    # Search for the user DN -->
    if sticky and self.settings.USER_SEARCH:
        self._user_dn = self._search_for_user_dn()

    except ldap.INVALID_CREDENTIALS:
        raise self.AuthenticationFailed("user DN/password rejected by LDAP server.")

backend._LDAPUser._authenticate_user_dn = monkey
Другие вопросы по тегам