在LDAP身份验证的情况下,通常用于身份验证的参数是什么.我想使用DN对于通过ldap登录的用户来说会很头疼,因为它太大而无法记住.如何使用uid或sAMAccountName进行身份验证的选项在我的实现中,我检索相应的uid或sAMAccountName的dn并继续进行身份验证.
我走的正确吗?
在LDAP中,可以验证连接或会话.当LDAP客户端与LDAP目录服务器建立新连接时,该连接具有匿名授权状态.LDAP客户端可以使用BIND请求请求更改授权状态.
BIND请求有两种形式:简单和SASL.Simple使用专有名称和密码,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=comou=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所需的全部内容.这里的关于部分的链接
LDAP服务器只能理解LDAP查询; 他们没有像我这样的"用户名",而且我已经习惯了.
对于LDAP,要对某人进行身份验证,您需要在LDAP中发送该人员(或实体)条目的可分辨名称 ; 以及他们的密码.
由于您提到了sAMAccountName,我假设您正在使用Active Directory.Active Directory允许匿名绑定 - 这意味着您可以连接到它而无需提供任何凭据; 但如果不提供凭据,则无法执行任何查找.
如果您正在使用python-ldapCython(而不是IronPython,它可以访问各种.NET API,使这个过程变得非常简单); 然后你按照这些步骤.
您通常使用具有适当的权限树预先设定的用户,并连接到与该用户的目录第一,然后使用该用户的认证过程的其余部分的访问; 通常是这样的:
所以你需要两个主要的东西:
以下是一些可以为您执行此操作的粗略代码:
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13972 次 |
| 最近记录: |