Installation:
git submodule add https://github.com/Domisys/LdapBundle.git vendor/bundles/OpenSky/Bundle/LdapBundle
Update app/autoload.php to register the OpenSky namespace:
$loader->registerNamespaces(array(
'OpenSky' => __DIR__.'/../vendor/bundles',
'Zend' => __DIR__.'/../vendor/zendframework/zendframework/library',
));
Enable the Bundle:
Add to app/AppKernel.php:
new OpenSky\Bundle\LdapBundle\OpenSkyLdapBundle(),
Configure LDAP:
Add to app/config/config.yml:
opensky_ldap:
host: 'ldap.example.com'
port: 389
use_ssl: false
base_dn: 'dc=example,dc=com'
username: 'cn=admin,dc=example,dc=com'
password: 'admin_password'
user_search_filter: '(uid=%s)'
group_search_filter: '(member=%s)'
user_class: 'inetOrgPerson'
group_class: 'groupOfNames'
First Use Case: Secure a route with LDAP authentication:
# app/config/security.yml
security:
providers:
ldap_provider:
id: opensky_ldap.user_provider
firewalls:
secured_area:
pattern: ^/admin
http_basic: ~
provider: ldap_provider
UserProvider Integration:
The bundle provides OpenSky\Bundle\LdapBundle\Security\User\LdapUserProvider, which implements Symfony’s UserProviderInterface. Extend or override its methods (e.g., loadUserByUsername) to customize LDAP queries:
// src/Acme/User/LdapUserProvider.php
class CustomLdapUserProvider extends \OpenSky\Bundle\LdapBundle\Security\User\LdapUserProvider {
protected function getUserSearchFilter($username) {
return '(sAMAccountName=' . $username . ')'; // Active Directory example
}
}
Register it in security.yml:
providers:
custom_ldap_provider:
id: acme.user_provider
Role Mapping:
Map LDAP groups to Symfony roles in config.yml:
opensky_ldap:
roles:
'cn=admins,ou=groups,dc=example,dc=com': 'ROLE_ADMIN'
'cn=editors,ou=groups,dc=example,dc=com': 'ROLE_EDITOR'
Custom User Objects:
Create a User class extending OpenSky\Bundle\LdapBundle\Security\User\LdapUser to add custom properties:
class AcmeUser extends \OpenSky\Bundle\LdapBundle\Security\User\LdapUser {
public function getFullName() {
return $this->getAttribute('givenName') . ' ' . $this->getAttribute('sn');
}
}
Configure in config.yml:
opensky_ldap:
user_class: 'Acme\User\AcmeUser'
Group-Based Access Control: Use Symfony’s voter system to restrict actions by LDAP group membership:
// src/Acme/Security/Voter/AdminVoter.php
class AdminVoter extends AbstractVoter {
public function vote(TokenInterface $token, $object, array $attributes) {
$user = $token->getUser();
if ($user instanceof \OpenSky\Bundle\LdapBundle\Security\User\LdapUser) {
return $user->hasRole('ROLE_ADMIN') ? self::ACCESS_GRANTED : self::ACCESS_DENIED;
}
return self::ACCESS_ABSTAIN;
}
}
Zend LDAP Dependency:
app/autoload.php).$ldap = new \Zend\Ldap\Ldap();
$ldap->connect('ldap.example.com');
var_dump($ldap->getLastError()); // Check connection errors
Filter Syntax:
(uid=john) works for inetOrgPerson.(sAMAccountName=john) is required for Active Directory.ldapsearch before implementing.SSL/TLS Issues:
use_ssl: true, ensure your LDAP server supports StartTLS or uses LDAPS (port 636).$ldap->setOption(\Zend\Ldap\LdapOptions::OPTION_PROTOCOL_VERSION, 3);
$ldap->setOption(\Zend\Ldap\LdapOptions::OPTION_REFERRALS, false);
Base DN Scope:
base_dn (e.g., dc=example,dc=com) slows queries. Narrow it to the OU containing users/groups:
base_dn: 'ou=users,dc=example,dc=com'
Password Hashing:
Enable Logging:
Add to config.yml:
opensky_ldap:
debug: true
Logs appear in app/logs/dev.log.
LDAP Query Logging: Extend the provider to log queries:
class DebugLdapUserProvider extends \OpenSky\Bundle\LdapBundle\Security\User\LdapUserProvider {
protected function doLoadUserByUsername($username) {
$this->logger->debug('LDAP Search: ' . $this->getUserSearchFilter($username));
return parent::doLoadUserByUsername($username);
}
}
Connection Timeouts:
Configure timeouts in config.yml:
opensky_ldap:
timeout: 5 # seconds
Custom Attributes:
Fetch additional LDAP attributes in loadUserByUsername:
$user->setAttribute('extensionAttribute3', $entry->extensionAttribute3);
Dynamic Role Assignment:
Override refreshUser to update roles on login:
public function refreshUser(UserInterface $user) {
$user->setRoles($this->fetchRolesFromLdap($user->getUsername()));
return $user;
}
Multi-Domain LDAP: Implement a chain provider to query multiple LDAP servers:
class MultiLdapUserProvider implements UserProviderInterface {
private $providers;
public function __construct(array $providers) {
$this->providers = $providers;
}
public function loadUserByUsername($username) {
foreach ($this->providers as $provider) {
try {
return $provider->loadUserByUsername($username);
} catch (UsernameNotFoundException $e) {
continue;
}
}
throw new UsernameNotFoundException();
}
}
Caching:
Cache LDAP results to reduce server load (use Symfony\Component\Cache):
$cache = $this->container->get('cache.app');
$cachedUser = $cache->get($username);
if ($cachedUser) return $cachedUser;
How can I help you explore Laravel packages today?