【问题标题】:Django Auth LDAP - Direct Bind using sAMAccountNameDjango Auth LDAP - 使用 sAMAccountName 直接绑定
【发布时间】:2013-05-19 06:23:03
【问题描述】:

有两种方法可以使用 Django Auth LDAP 对用户进行身份验证

  1. 搜索/绑定和
  2. 直接绑定。

第一个涉及匿名或使用固定帐户连接到 LDAP 服务器并搜索身份验证用户的可分辨名称。然后我们可以尝试再次与用户密码绑定。

第二种方法是从用户名中导出用户的DN,并尝试直接绑定为用户。

我希望能够使用尝试访问应用程序的用户的用户 ID (sAMAccountName) 和密码进行直接绑定。请让我知道是否有办法实现这一目标?目前,由于下面解释的问题,我似乎无法完成这项工作。

在我的例子中,LDAP 中用户的 DN 格式如下

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

这基本上翻译为'CN=FirstName LastName,OU=Users,OU=Central,OU=US,DC=client,DC=corp'

这使我无法使用直接绑定,因为用户的 sAMAccountNamesjones,这是与用户名 (%user) 对应的参数,我无法找到一种方法来构建一个正确的 AUTH_LDAP_USER_DN_TEMPLATE 来派生用户的 DN。

由于上述问题,我现在正在使用搜索/绑定,但这需要我在 AUTH_LDAP_BIND_DNAUTH_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'

期待这里的好人提供一些指导。

【问题讨论】:

    标签: python django active-directory django-authentication django-auth-ldap


    【解决方案1】:

    上面的答案对我不起作用,但我找到了一种让它起作用的方法。 诀窍是使用 sAMAAcountname 结合要绑定的域名。

    1. 修改模板 DN 以使其使用 username@domain.com 格式。
    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
    

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题。

      我在现已删除的 bitbucket 存储库中遇到票证 21。 (cant-bind-and-search-on-activedirectory)。这些问题没有迁移到their github,但作者提出了一种方法来更改django-auth-ldap 的库文件,以便它可以直接绑定。

      归结为更改 <python library path>/django_auth_ldap/backend.py 以在 _authenticate_user_dn 中包含两行:

      if sticky and ldap_settings.AUTH_LDAP_USER_SEARCH:
          self._search_for_user_dn()
      

      我能够让它在运行 Arch Linux 3.9.8-1-ARCH 的本地机器上运行,但我无法在运行 Ubuntu 13.04 的开发服务器上复制它。

      希望这会有所帮助。

      【讨论】:

      • 谢谢@amethystdragon 看起来这会解决我的问题。我很快就会试一试。
      【解决方案3】:

      我认为使用直接绑定(如下所示)然后在登录界面中传递通用名称就可以完成这项工作,因此不需要设置静态身份验证凭据。

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

      【讨论】:

        【解决方案4】:

        我也有这个问题,但我不想修改settings.py 文件。我的解决方法是注释掉“AUTH_LDAP_USER_DN_TEMPLATE =”uid=%(user)s,ou=path,dc=to,dc=domain”行。作为故障排除的一部分,我还添加了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
        

        【讨论】:

          【解决方案5】:

          我也遇到过这个问题,旧的 ldap 服务器的 dn 以 uid 开头,但新服务器的 DN 以 CN('Steven Jones')开头。我在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)')
          

          【讨论】:

            【解决方案6】:

            (这实际上是对@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
            

            【讨论】:

            • 非常感谢。我也试试这个
            猜你喜欢
            • 1970-01-01
            • 2019-04-11
            • 2011-08-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-15
            • 1970-01-01
            • 2019-09-18
            相关资源
            最近更新 更多