我有一个针对Ldap服务器进行身份验证的Symfony登录表单。我可以使用samaccountname或userprincipalname以及我的配置设置中的uid键成功查询和认证用户。我希望能够允许用户输入他们的用户名或他们的username@domain.com
我在LdapUserProviderClass的loadUserbyUsername()方法中的用户名上尝试了preg_replace(我知道这并不理想)。这需要一个用户名(例如username@domain.com)并传递用户名。我能够验证从Ldap服务器返回了正确的用户,但是我仍然返回带有“无效凭据”的登录表单。我相信会处理AuthenticationUtils类请求中发生这种情况的原因,并且请求中的用户名仍为username@domain.com,并且与来自Ldap身份验证的用户对象中的用户名(即用户名)不匹配。如果有人对如何完成允许用户名@ domain.com和用户名针对Ldap进行身份验证提出建议,我将不胜感激。
SecurityController.php
public function login(Request $request, AuthenticationUtils $authenticationUtils): Response
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
$newLastUsername = trim(preg_replace('/@.*/', '',$lastUsername));
return $this->render('security/login.html.twig', ['last_username' => $newLastUsername, 'error' => $error]);
}
security.yml
providers:
dsg_ldap:
ldap:
service: Symfony\Component\Ldap\Ldap
base_dn: '%env(BASE_DSN)%'
search_dn: '%env(SEARCH_DN)%'
search_password: '%env(SEARCH_PWD)%'
uid_key: '%env(UID_KEY)%'
#filter: '({uid_key}={_username})'
default_roles: ROLE_USER
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
form_login_ldap:
login_path: login
check_path: login
service: Symfony\Component\Ldap\Ldap
provider: dsg_ldap
dn_string: '%env(DN_STRING)%\{username}'
我的LdapUserProvider.php
class LdapUserProvider extends SymfonyLdapUserProvider
{
/** @var array maps ldap groups to roles */
private $groupMapping = [
'**' => '**',
'**' => '**',
'**' => '**',
'**' => '**'
];
/** @var string extracts group name from dn string */
private $groupNameRegExp = '/CN=(.+?),/';
protected function loadUser($username, Entry $entry)
{
$roles = ['ROLE_USER'];
// Check if the entry has attribute with the group
if (!$entry->hasAttribute('memberOf')) {
return new User($username, '', $roles);
}
// Iterate through each group entry line
foreach ($entry->getAttribute('memberOf') as $groupLine) {
// Extract the group name from the line
$groupName = $this->getGroupName($groupLine);
// Check if the group is in the mapping
if (array_key_exists($groupName, $this->groupMapping)) {
// Map the group to the role(s) the user will have
$roles[] = $this->groupMapping[$groupName];
}
}
// Create and return the user object
return new User($username, null, $roles);
}
/**
* Get the group name from the DN
* @param string $dn
* @return string
*/
private function getGroupName($dn)
{
$matches = [];
return preg_match($this->groupNameRegExp, $dn, $matches) ? $matches[1] : '';
}
}
Symfony \ Component \ Security \ Core \ User \ LdapUserProvider.php
public function loadUserByUsername($username)
{
try {
$this->ldap->bind($this->searchDn, $this->searchPassword);
// what i added
$username = trim(preg_replace('/@.*/', '',$username));
$username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_FILTER);
$query = str_replace('{username}', $username, $this->defaultSearch);
$search = $this->ldap->query($this->baseDn, $query);
} catch (ConnectionException $e) {
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username), 0, $e);
}
$entries = $search->execute();
$count = \count($entries);
if (!$count) {
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
}
if ($count > 1) {
throw new UsernameNotFoundException('More than one user found');
}
$entry = $entries[0];
try {
if (null !== $this->uidKey) {
$username = $this->getAttributeValue($entry, $this->uidKey);
}
} catch (InvalidArgumentException $e) {
}
return $this->loadUser($username, $entry);
}
答案 0 :(得分:0)
在loadUserByUsername
函数中,如果第一个查询失败,则添加另一个查询。您的$this->defaultSearch
可能是一个代表LDAP过滤器的常数。
如果您在第一个if (!$count) {...}
中创建相同的行,如下所示:
$query = str_replace('{username}', $username, "(userPrincipalName={username})");
然后执行该查询,您正在第二次搜索形式为 user @ domain
的userPrincipalName。