哪个参数用于LDAP中的身份验证

时间:2012-08-30 05:04:36

标签: ldap

在LDAP身份验证的情况下,身份验证通常使用的参数是什么?我想使用DN对于通过ldap登录的用户来说会很头疼,因为它太大而无法记住。 如何使用 uid sAMAccountName 进行身份验证的选项在我的实现中,我检索相应的uid或sAMAccountName的dn并继续进行身份验证。

我走的是正确的轨道吗?

3 个答案:

答案 0 :(得分:9)

在LDAP中,可以验证连接会话。当LDAP客户端与LDAP目录服务器建立新连接时,该连接的授权状态为 anonymous 。 LDAP客户端可以使用BIND请求请求更改授权状态。

BIND请求有两种形式:simple和SASL。简单使用专有名称和密码,SASL使用机制中的一种,例如,PLAIN,LOGIN,CRAM-MD5,DIGEST-MD5,GSSAPI和EXTERNAL - 所有这些除外GSSAPI和EXTERNAL太弱,无法在生产场景或任务关键领域中使用。

要使用简单BIND,请构造BIND请求并将其传输到LDAP目录服务器。 LDAP目录服务器将使用BIND响应进行响应,其中包含结果代码。结果代码是一个整数,其他任何零都表示BIND请求失败。如果结果代码为零,则BIND请求成功,并且会话授权状态已更改为BIND请求中使用的可分辨名称的状态。

同一连接/会话上的每个后续BIND请求都会将授权状态设置为匿名,并且同一连接/会话上的每个连续成功BIND请求都会将授权状态设置为与身份验证ID相关联的授权状态,在简单BIND的情况下是可分辨名称,但可能完全是使用SASL的其他东西 - 现代专业质量服务器可以将传入名称映射到不同的DN。

使用哪种语言,构造BIND请求,将其传输到服务器,并解释响应。

更新

如果不知道可分辨名称,或者过于繁琐(通常是Web应用程序用户不知道如何进行身份验证并且不关心他们是否知道),LDAP应用程序应该在目录中搜索用户。成功的搜索响应始终包含可分辨名称,然后在简单的BIND中使用。

搜索至少包含以下内容:

  • 基础对象:优于用户的专有名称,例如dc=example,dc=com
  • 范围:基本级别,低于基础的一级,或低于基础的子树。例如,如果用户位于ou=people,dc=example,dc=com的从属位置,请使用基础对象ou=people,dc=example,dc=com和范围one-level。这些搜索参数可找到以下条目:uid=user1,ou=people,dc=example,dc=com
  • 过滤器:缩小返回给客户端的可能搜索结果,例如(objectClass=inetOrgPerson)
  • 请求的属性列表:要返回到客户端的条目的属性。在这种情况下,使用1.1,这意味着无属性并返回DN(可分辨名称),这就是简单BIND所需的全部内容。

另见

关于here

部分中的链接

答案 1 :(得分:6)

LDAP服务器只能理解LDAP查询;他们没有像你这样的“用户名”,而且我已经习惯了。

对于LDAP,要对某人进行身份验证,您需要在LDAP中发送该人(或实体)条目的专有名称;以及他们的密码。

由于您提到 sAMAccountName ,我假设您正在使用Active Directory。 Active Directory允许匿名绑定 - 这意味着您可以连接到它而无需提供任何凭据;但是如果没有提供凭据就无法进行任何查找。

如果您正在使用python-ldap和Cython(而不是IronPython,它可以访问各种.NET API,使这个过程变得非常简单);然后你按照这些步骤。

通常,您使用对树具有适当权限的预设用户,并使用该用户首先连接到该目录,然后使用该用户的访问权限进行其余的身份验证过程;通常是这样的:

  1. 使用预设用户连接到AD。
  2. 使用预设用户的凭据查询活动目录,并根据用户将在表单中输入的 sAMAccountName 搜索专有名称。
  3. 尝试使用步骤2中的专有名称和用户在其表单中输入的密码再次连接到Active Directory。
  4. 如果此连接成功,则会对用户进行身份验证。
  5. 所以你需要两个主要的东西:

    1. 登录属性(这是LDAP理解的“用户名”)
    2. 为您的用户提取信息的LDAP查询
    3. 以下是一些可以为您完成此操作的粗略代码:

      AD_USER = 'your super user'
      AD_PASSWORD = 'your super user password'
      
      AD_BIND_ATTR = 'userPrincipalName' # this is the "login" for AD
      AD_URL = "ldap://your-ad-server"
      AD_DN = "DC=DOMAIN,DC=COM"
      AD_LOGIN_ATTR = 'sAMAccountName' # this is what you user will enter in the form
                                       # as their "login" name,
                                       # this is what they use to login to Windows
      
      # A listing of attributes you want to fetch for the user
      AD_ATTR_SEARCH = ['cn',
                        'userPrincipalName',
                        'distinguishedName',
                        'mail',
                        'telephoneNumber','sAMAccountName']
      
      def _getbinduser(user):
          """ This method returns the bind user string for the user"""
          user_dn = AD_DN
          login_attr = '(%s=%s)' % (AD_LOGIN_ATTR,user)
          attr_search = AD_ATTR_SEARCH
      
          conn = ldap.initialize(AD_URL)
          conn.set_option(ldap.OPT_REFERRALS,0)
          conn.set_option(ldap.OPT_PROTOCOL_VERSION,3)
          try:
              conn.bind(AD_USER,AD_PASSWORD)
              conn.result()
          except:
              exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
              # Exit the script and print an error telling what happened.
              sys.exit("LDAP Error (Bind Super User)\n ->%s" % exceptionValue)
          try:
              result = conn.search_s(user_dn,
                                     ldap.SCOPE_SUBTREE,
                                     login_attr, attr_search)
          except:
              exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
              # Exit the script and print an error telling what happened.
              sys.exit("LDAP Error (Search)\n ->%s" % exceptionValue)
      
          # Return the user's entry from AD, which includes
          # their 'distinguished name'
          # we use this to authenticate the credentials the
          # user has entered in the form
          return result[0][1]
      
      def authenticate(user,password):
      
          bind_attr = AD_BIND_ATTR
          user_dn = AD_DN
          login_attr = '(%s=%s)' % (AD_LOGIN_ATTR,user)
          data = _getbinduser(user)
      
          if len(data) == 1:
              return None
      
          # Information we want to return from the directory
          # for each user, season to taste.
      
          info = {}
          info['name'] = data['cn'][0]
          info['email'] = data['mail'][0]
          try:
              info['phone'] = data['telephoneNumber'][0]
          except KeyError:
              info['phone'] = 'Not Available'
      
          conn = ldap.initialize(Config.AD_URL)
          conn.set_option(ldap.OPT_REFERRALS,0)
          conn.set_option(ldap.OPT_PROTOCOL_VERSION,3)
      
          try:
              # Now we have the "bind attribute" (LDAP username) for our user
              # we try and connect to see if LDAP will authenticate
              conn.bind(data[bind_attr][0],password)
              conn.search(user_dn,ldap.SCOPE_SUBTREE,login_attr,None)
              conn.result()
              return info
          except (ldap.INVALID_CREDENTIALS,ldap.OPERATIONS_ERROR):
              return None
      

答案 2 :(得分:0)

对特里的出色评论进行了一次小规模扩张。如果将所有用户存储在DIT的同一部分中,并使用相同的属性来识别它们,则可以通过编程方式构建DN,而不是搜索它。