在 python 和 flask 中搜索我们在登录 ldap3 时提供的 id 的 givenName 和 surnam



我能够使用 ldap3 为我的烧瓶应用程序设置身份验证。我们使用活动目录,因此我使用 ldap3 连接到我们的活动目录并根据输入凭据验证用户。我遇到的问题是它的设置方式。下面是您所看到的代码:

def global_ldap_authentication(user_id, user_pwd):
ldap_user_id = user_id.strip()
ldap_user_pwd = user_pwd.strip()
ldsp_server = f'our_internal_server'
root_dn = "OU=Users,OU=AUS - Austin,OU=Americas,OU=JCJJ,DC=jcjj,DC=com"
user = f'CN=Dave Simmon - {ldap_user_id},{root_dn}'
server = Server(ldsp_server, get_info=ALL)
connection = Connection(server, user=user, password=ldap_user_pwd)
connection.start_tls()

if not conn.bind():
print(f" *** cannot bind to ldap server: {conn.last_error}")
l_success_msg = f' *** Failed Authentication: {conn.last_error}'
else:
print(f" *** Successful bind to ldap server")
l_success_msg = 'Happy'
return l_success_msg

如您所见,这将连接到我的 ldap 服务器并让我登录。我的登录路由很简单,因为它采用 userID 和密码,并使用这些属性调用此global_ldap_authentication函数,并在用户中登录,如果它针对我们拥有的活动目录进行身份验证。问题出在变量"user"上,我在其中指定了一个名称 Dave Simmon 以连接到 ldap,这意味着只有用户 Dave simmon 可以使用他的用户 ID(A5564,这是用户 ID 的数字)和他的密码登录我的应用程序。

我尝试了其他连接到ldap目录的方法,但没有成功,它只能以这种方式工作。 我终于找到了一种技术来使这个名字变数,而不是戴夫·西蒙。我们有一个服务帐户,我的计划是每次调用此函数时使用该服务帐户及其密码登录 ldap,并且由于我将从登录页面中的表单中获取用户 ID 和密码,因此我想在 ldap 活动目录中搜索属于任何人在登录表单中输入的用户 ID 的给定名称和姓氏 (sn),然后将该 Dave simmon 替换为该给定名称和来自活动目录的 SN。

这将允许该目录中的任何人登录到我的应用程序。问题是我很难弄清楚该怎么做。如何根据收到的用户 ID 搜索给定名称和姓氏 (sn)。用户 ID 是唯一的,每个用户 ID 都映射到其用户各自的名字和姓氏。因此,当在我的登录表单中输入A5564时,我应该能够从我的活动目录中查询Dave Simmon,以便我可以成功连接和登录。

我试图使它尽可能详细。任何帮助将不胜感激!!

我的登录路线超级简单:

@app.route('/', methods=['GET', 'POST'])
def login():
form = LoginForm()
if request.method in ('POST'):
login_id = form.userid.data
login_password = form.password.data

#used to pass argument to main_page
print(login_id)
session['login_id'] = login_id
login_msg = global_ldap_authentication(login_id, login_password)
#validate the connection
print(login_msg)
if login_msg == "Success":
return redirect(url_for('main_page'))
#return render_template('index.html')
else:
return render_template('login.html', form=form)
return render_template('login.html', form=form)

实现此目的的一种方法是使用"搜索和绑定"方法。

基本上,它包括在您的应用程序中使用经理/管理员帐户,该帐户将绑定并搜索给定用户名/ID 的用户的目录,以便您可以检索他的 DN,而不必构建它。然后,您最终可以使用他的 dn/密码绑定进行身份验证。唯一的条件是用户必须提供一个唯一标识符,该标识符作为属性存储在其目录条目中,以便可以有效地过滤搜索以仅匹配此用户。

在 AD 中,有两个用户属性可用于匹配帐户登录名:

  • userPrincipalName :userPrincipalName 属性是用户的登录名。该属性由用户主体组成 name (UPN),这是 Windows 用户最常用的登录名。 用户通常使用其 UPN 登录到域。UPN 由 UPN 前缀(用户帐户名)和 UPN 后缀(DNS 域名)组成。前缀使用"@"符号与后缀连接。例如,"someone@ example.com"。

  • sAMAccountName :sAMAccountName 属性是一个登录名,用于支持以前版本的 Windows 中的客户端和服务器, 例如 Windows NT 4.0、Windows 95、Windows 98 和 LAN Manager。这 登录名必须为 20 个字符或更少,并且在所有字符中是唯一的 域中的安全主体对象。

那么问题是,诸如A5564之类的用户ID是否与这些属性之一匹配?用户是否在表单中提供其帐户登录名?如果没有,则需要更改该标识,或者将它们在 AD 中自己的用户条目中提供的 ID 注册为需要用于筛选搜索的特定属性。

我最终想通了,以防万一有人需要它。我能够使用它。

conn.search('OU=AUS - Austin,OU=Americas,OU=JCJJ,DC=jcjj,DC=com', '(&(objectclass=person)(sAMAccountName={id}))'.format(id=ldap_user_name), attributes=['CN'])
entry = conn.entries[0]
name = entry.CN

因此,正如我之前所说,我首先能够使用服务帐户和密码连接到ldap活动目录。然后,我根据用户在我的登录表单中输入的"id"运行上述搜索。然后我提到我想要"CN"属性,它以这种格式返回名称:Dave Simmon - A5564。这正是我制作变量而不是硬编码所需要的。

因此,我将这个Dave Simmon - A5564存储在一个名为name的变量中,并使用此变量再次连接到我的ldap,并让用户看到我的应用程序的主页。现在,任何输入其ID的用户都将将其名称存储在名为"name"的变量中,并且将能够登录到网页。

谢谢!

最新更新