Skip to content

Commit e5ab85d

Browse files
committed
feature #32824 [Ldap] Add security LdapUser and provider (chalasr)
This PR was merged into the 4.4 branch. Discussion ---------- [Ldap] Add security LdapUser and provider | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Moves `LdapUserProvider` from `Security\Core` to the Ldap component, the provider now deals with a new `LdapUser` aware of its ldap `Entry` (should help in #31843). Commits ------- 6736cdfec3 [Ldap] Add security LdapUser and provider
2 parents 6119cc0 + 443a1a7 commit e5ab85d

File tree

3 files changed

+12
-107
lines changed

3 files changed

+12
-107
lines changed

Tests/User/LdapUserProviderTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\Security\Core\User\LdapUserProvider;
2121

2222
/**
23+
* @group legacy
2324
* @requires extension ldap
2425
*/
2526
class LdapUserProviderTest extends TestCase

User/LdapUserProvider.php

Lines changed: 8 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -11,89 +11,22 @@
1111

1212
namespace Symfony\Component\Security\Core\User;
1313

14+
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', LdapUserProvider::class, BaseLdapUserProvider::class), E_USER_DEPRECATED);
15+
1416
use Symfony\Component\Ldap\Entry;
15-
use Symfony\Component\Ldap\Exception\ConnectionException;
16-
use Symfony\Component\Ldap\LdapInterface;
17-
use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
17+
use Symfony\Component\Ldap\Security\LdapUserProvider as BaseLdapUserProvider;
1818
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
19-
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
2019

2120
/**
2221
* LdapUserProvider is a simple user provider on top of ldap.
2322
*
2423
* @author Grégoire Pineau <[email protected]>
2524
* @author Charles Sarrazin <[email protected]>
25+
*
26+
* @deprecated since Symfony 4.4, use "Symfony\Component\Ldap\Security\LdapUserProvider" instead
2627
*/
27-
class LdapUserProvider implements UserProviderInterface
28+
class LdapUserProvider extends BaseLdapUserProvider
2829
{
29-
private $ldap;
30-
private $baseDn;
31-
private $searchDn;
32-
private $searchPassword;
33-
private $defaultRoles;
34-
private $uidKey;
35-
private $defaultSearch;
36-
private $passwordAttribute;
37-
private $extraFields;
38-
39-
public function __construct(LdapInterface $ldap, string $baseDn, string $searchDn = null, string $searchPassword = null, array $defaultRoles = [], string $uidKey = null, string $filter = null, string $passwordAttribute = null, array $extraFields = [])
40-
{
41-
if (null === $uidKey) {
42-
$uidKey = 'sAMAccountName';
43-
}
44-
45-
if (null === $filter) {
46-
$filter = '({uid_key}={username})';
47-
}
48-
49-
$this->ldap = $ldap;
50-
$this->baseDn = $baseDn;
51-
$this->searchDn = $searchDn;
52-
$this->searchPassword = $searchPassword;
53-
$this->defaultRoles = $defaultRoles;
54-
$this->uidKey = $uidKey;
55-
$this->defaultSearch = str_replace('{uid_key}', $uidKey, $filter);
56-
$this->passwordAttribute = $passwordAttribute;
57-
$this->extraFields = $extraFields;
58-
}
59-
60-
/**
61-
* {@inheritdoc}
62-
*/
63-
public function loadUserByUsername($username)
64-
{
65-
try {
66-
$this->ldap->bind($this->searchDn, $this->searchPassword);
67-
$username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_FILTER);
68-
$query = str_replace('{username}', $username, $this->defaultSearch);
69-
$search = $this->ldap->query($this->baseDn, $query);
70-
} catch (ConnectionException $e) {
71-
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username), 0, $e);
72-
}
73-
74-
$entries = $search->execute();
75-
$count = \count($entries);
76-
77-
if (!$count) {
78-
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
79-
}
80-
81-
if ($count > 1) {
82-
throw new UsernameNotFoundException('More than one user found');
83-
}
84-
85-
$entry = $entries[0];
86-
87-
try {
88-
if (null !== $this->uidKey) {
89-
$username = $this->getAttributeValue($entry, $this->uidKey);
90-
}
91-
} catch (InvalidArgumentException $e) {
92-
}
93-
94-
return $this->loadUser($username, $entry);
95-
}
96-
9730
/**
9831
* {@inheritdoc}
9932
*/
@@ -117,42 +50,12 @@ public function supportsClass($class)
11750
/**
11851
* Loads a user from an LDAP entry.
11952
*
120-
* @param string $username
121-
* @param Entry $entry
122-
*
12353
* @return User
12454
*/
12555
protected function loadUser($username, Entry $entry)
12656
{
127-
$password = null;
128-
$extraFields = [];
129-
130-
if (null !== $this->passwordAttribute) {
131-
$password = $this->getAttributeValue($entry, $this->passwordAttribute);
132-
}
133-
134-
foreach ($this->extraFields as $field) {
135-
$extraFields[$field] = $this->getAttributeValue($entry, $field);
136-
}
137-
138-
return new User($username, $password, $this->defaultRoles, true, true, true, true, $extraFields);
139-
}
140-
141-
/**
142-
* Fetches a required unique attribute value from an LDAP entry.
143-
*/
144-
private function getAttributeValue(Entry $entry, string $attribute)
145-
{
146-
if (!$entry->hasAttribute($attribute)) {
147-
throw new InvalidArgumentException(sprintf('Missing attribute "%s" for user "%s".', $attribute, $entry->getDn()));
148-
}
149-
150-
$values = $entry->getAttribute($attribute);
151-
152-
if (1 !== \count($values)) {
153-
throw new InvalidArgumentException(sprintf('Attribute "%s" has multiple values.', $attribute));
154-
}
57+
$ldapUser = parent::loadUser($username, $entry);
15558

156-
return $values[0];
59+
return new User($ldapUser->getUsername(), $ldapUser->getPassword(), $ldapUser->getRoles(), true, true, true, true, $ldapUser->getExtraFields());
15760
}
15861
}

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
"symfony/event-dispatcher": "^4.3",
2626
"symfony/expression-language": "^3.4|^4.0|^5.0",
2727
"symfony/http-foundation": "^3.4|^4.0|^5.0",
28-
"symfony/ldap": "^3.4|^4.0|^5.0",
28+
"symfony/ldap": "^4.4|^5.0",
2929
"symfony/validator": "^3.4|^4.0|^5.0",
3030
"psr/log": "~1.0"
3131
},
3232
"conflict": {
3333
"symfony/event-dispatcher": "<4.3|>=5",
34-
"symfony/security-guard": "<4.3"
34+
"symfony/security-guard": "<4.3",
35+
"symfony/ldap": "<4.4"
3536
},
3637
"suggest": {
3738
"psr/container-implementation": "To instantiate the Security class",

0 commit comments

Comments
 (0)