简体   繁体   English

根据Django中的登录用户名获取LDAP组

[英]Get LDAP group based on login username in Django

I need to retrieve the list of groups a user is in, using an LDAP query in Django. 我需要使用Django中的LDAP查询来检索用户所在的群组列表。 The use case is: a user fills in his LDAP login credentials, and Django will authenticate him and will also assign his LDAP groups . 用例是:用户填写其LDAP登录凭据,并且Django将对其进行身份验证,并将分配其LDAP组

The user login works flawlessly, but I cannot filter groups using memberUid=%(user)s . 用户登录可以正常工作,但是我无法使用memberUid=%(user)s过滤组。 I'm looking for the right method to pass the username as a filter argument to "groupfilter" property . 我正在寻找将用户名作为过滤器参数传递给“ groupfilter”属性的正确方法 I tested the query with an LDAP application browser and seems to work properly. 我使用LDAP应用程序浏览器测试了查询,并且似乎可以正常工作。

  • OS: Ubuntu 14.04 x64 操作系统: Ubuntu 14.04 x64
  • Python version: 2.7.6 Python版本: 2.7.6
  • Django version: (1, 6, 11, 'final', 0) Django版本:1、6、11 ,“最终版本”,0)

RatticWeb LDAP configuration RatticWeb LDAP配置

I'm using RatticWeb django application to manage users' passwords with the following local configuration (see also Rattic repository wiki ): 我正在使用RatticWeb django应用程序通过以下本地配置来管理用户的密码(另请参见Rattic存储库Wiki ):

conf/local.cfg CONF / local.cfg

[ldap]
requirecert = True
# LDAP server details
uri = ldap://localhost:port
# Bind DN
binddn = cn=admin,dc=mydomain
bindpw = mypassword
# User parameters
userbase = ou=Users,dc=mydomain
userfilter = (uid=%(user)s)
#userfilter = (objectClass=person)
userfirstname = givenName
userlastname = sn
useldapgroups = True
# Set up the basic group parameters.
groupbase = ou=Groups,dc=mydomain
groupfilter = (&(objectClass=posixGroup)(memberUid=%(user)s))  
grouptype = PosixGroupType
# How do I find staff
#staff = cn=staff,ou=groups,dc=example,dc=com
loglevel = DEBUG

This configuration file is read by settings.py ( source code ): 该配置文件由settings.py源代码 )读取:

ratticweb/settings.py ratticweb / settings.py

 # Defaults to a bogus filter so that searching yields no errors in the log
 AUTH_LDAP_GROUP_FILTER = confget('ldap', 'groupfilter', '(objectClass=_fake)')
 AUTH_LDAP_USER_SEARCH = LDAPSearch(AUTH_LDAP_USER_BASE, ldap.SCOPE_SUBTREE, AUTH_LDAP_USER_FILTER)
 AUTH_LDAP_GROUP_SEARCH = LDAPSearch(AUTH_LDAP_GROUP_BASE, ldap.SCOPE_SUBTREE, AUTH_LDAP_GROUP_FILTER)

LOG LOG

Now, I need to filter LDAP group passing the username parameter coming from user login form, and I tried using the same format of userfilter but the server give me back the following error: 现在,我需要过滤传递来自用户登录表单的username参数的LDAP组,并且尝试使用相同格式的userfilter,但服务器将以下错误返回给我:

[Wed Jan 13 16:51:24.257325 2016] [:error] [pid 11280] 2016-01-13 16:51:24,256 [ERROR] Caught Exception while authenticating myusername
[Wed Jan 13 16:51:24.257438 2016] [:error] [pid 11280] Traceback (most recent call last):
[Wed Jan 13 16:51:24.257478 2016] [:error] [pid 11280]   File "/usr/local/lib/python2.7/dist-packages/django_auth_ldap/backend.py", line 323, in authenticate
[Wed Jan 13 16:51:24.257515 2016] [:error] [pid 11280]     self._get_or_create_user()
[Wed Jan 13 16:51:24.257550 2016] [:error] [pid 11280]   File "/usr/local/lib/python2.7/dist-packages/django_auth_ldap/backend.py", line 539, in _get_or_create_user
[Wed Jan 13 16:51:24.257586 2016] [:error] [pid 11280]     self._mirror_groups()
[Wed Jan 13 16:51:24.257620 2016] [:error] [pid 11280]   File "/usr/local/lib/python2.7/dist-packages/django_auth_ldap/backend.py", line 638, in _mirror_groups
[Wed Jan 13 16:51:24.257697 2016] [:error] [pid 11280]     group_names = self._get_groups().get_group_names()
[Wed Jan 13 16:51:24.257734 2016] [:error] [pid 11280]   File "/usr/local/lib/python2.7/dist-packages/django_auth_ldap/backend.py", line 755, in get_group_names
[Wed Jan 13 16:51:24.257770 2016] [:error] [pid 11280]     group_infos = self._get_group_infos()
[Wed Jan 13 16:51:24.257804 2016] [:error] [pid 11280]   File "/usr/local/lib/python2.7/dist-packages/django_auth_ldap/backend.py", line 803, in _get_group_infos
[Wed Jan 13 16:51:24.257835 2016] [:error] [pid 11280]     self._group_search)
[Wed Jan 13 16:51:24.257864 2016] [:error] [pid 11280]   File "/usr/local/lib/python2.7/dist-packages/django_auth_ldap/config.py", line 374, in user_groups
[Wed Jan 13 16:51:24.257893 2016] [:error] [pid 11280]     groups = search.execute(ldap_user.connection)
[Wed Jan 13 16:51:24.257928 2016] [:error] [pid 11280]   File "/usr/local/lib/python2.7/dist-packages/django_auth_ldap/config.py", line 150, in execute
[Wed Jan 13 16:51:24.257957 2016] [:error] [pid 11280]     filterstr = self.filterstr % filterargs
[Wed Jan 13 16:51:24.257990 2016] [:error] [pid 11280] TypeError: format requires a mapping

EDIT: Cause of the error 编辑:错误原因

The constructor of LDAPSearch populates its attributes as follows: LDAPSearch的构造LDAPSearch填充其属性,如下所示:

self.base_dn = 'groupbase = ou=Groups,dc=mydomain'
self.scope = ldap.SCOPE_SUBTREE
self.filterstr = '(&(objectClass=posixGroup)(memberUid=%(user)s))'

/usr/local/lib/python2.7/dist-packages/django_auth_ldap/config.py #150 /usr/local/lib/python2.7/dist-packages/django_auth_ldap/config.py#150

def execute(self, connection, filterargs=()):
    """
    Executes the search on the given connection (an LDAPObject). filterargs
    is an object that will be used for expansion of the filter string.

    The python-ldap library returns utf8-encoded strings. For the sake of
    sanity, this method will decode all result strings and return them as
    Unicode.
    """
    try:
        filterstr = self.filterstr % filterargs
        results = connection.search_s(self.base_dn.encode('utf-8'),
                                      self.scope,
                                      filterstr.encode('utf-8'))
    except ldap.LDAPError, e:
        results = []
        logger.error(u"search_s('%s', %d, '%s') raised %s" %
                     (self.base_dn, self.scope, filterstr, pprint.pformat(e)))

    return self._process_results(results)

At last, I've found the solution: 最后,我找到了解决方案:

conf/local.cfg CONF / local.cfg

[ldap]
....
# Set up the basic group parameters.
groupbase = ou=Groups,dc=mydomain
groupfilter = (objectClass=posixGroup)  
grouptype = PosixGroupType
...

The key factor is the use of the groupType PosixGroupType , because the query on Groups would be filtered on the memberUid parameter by Django Auth LDAP (observe the else part of the user_groups function: 关键因素是使用groupType PosixGroupType ,因为对组的查询将由Django Auth LDAP在memberUid参数上进行过滤(请观察user_groups函数的else部分:

class PosixGroupType(LDAPGroupType):
  """
  An LDAPGroupType subclass that handles groups of class posixGroup.
  """
  def user_groups(self, ldap_user, group_search):
    """
    Searches for any group that is either the user's primary or contains the
    user as a member.
    """
    groups = []

    try:
        user_uid = ldap_user.attrs['uid'][0]

        if 'gidNumber' in ldap_user.attrs:
            user_gid = ldap_user.attrs['gidNumber'][0]
            filterstr = u'(|(gidNumber=%s)(memberUid=%s))' % (
                self.ldap.filter.escape_filter_chars(user_gid),
                self.ldap.filter.escape_filter_chars(user_uid)
            )
        else:
            filterstr = u'(memberUid=%s)' % (
                self.ldap.filter.escape_filter_chars(user_uid),
            )

        search = group_search.search_with_additional_term_string(filterstr)
        groups = search.execute(ldap_user.connection)
    except (KeyError, IndexError):
        pass

    return groups

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM