Symfony 3.4覆盖内置LdapUserProvider中的单个方法

时间:2019-03-15 14:20:16

标签: php symfony ldap

我试图在用户通过LDAP登录时根据其LDAP dn授予角色。 为此,我想从Symfony \ Component \ Security \ Core \ User \ LdapUserProvider中重写loadUser方法,但是如果我理解正确的话,我真的不知道如何进行(我在使用时是相当新的Symfony:p),它不是服务,而是其中一部分? 因此,有没有一种方法可以轻松地重写该方法,还是我需要重新定义整个Ldap服务?

我尝试过的是:

// app/config/services.yml
[...]
Symfony\Component\Ldap\Ldap:
    arguments: ['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
Symfony\Component\Security\Core\User\LdapUserProvider:
    class: AppBundle\Services\LdapUserProvider
Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
    arguments:
        - host: '%ldap_host%'
          port: '%ldap_port%'
// src/Services/LdapUserProvider.php
namespace AppBundle\Services;

use Symfony\Component\Ldap\Entry;

class LdapUserProvider extends \Symfony\Component\Security\Core\User\LdapUserProvider {
    protected function loadUser($username, Entry $entry)
    {
        $password = null;

        if (null !== $this->passwordAttribute) {
            $password = $this->getAttributeValue($entry, $this->passwordAttribute);
        }

        return new User($username, $password, array('ROLE_TEST'));
    }
}

但是,它当然不起作用,而且我没有ROLE_TEST角色。

预先感谢!

1 个答案:

答案 0 :(得分:0)

您可以使用本教程:

https://medium.com/@devstan/extended-ldap-with-symfony-3-30be6f1a36b1

,您应该创建一个实现LdapUser

UserInterface

1.LDAP用户提供者

<?php
namespace YourAppBundle\Security\User;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Ldap\Entry;
use Symfony\Component\Security\Core\User\LdapUserProvider as BaseLdapUserProvider;
class LdapUserProvider extends BaseLdapUserProvider
{
    /**
     * {@inheritdoc}
     */
    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof LdapUser) {
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
        }
        return new LdapUser($user->getUsername(), null, $user->getRoles(), $user->getLdapEntry());
    }
    /**
     * {@inheritdoc}
     */
    public function supportsClass($class)
    {
        return $class === 'YourAppBundle\Security\User\LdapUser';
    }
    /**
     * {@inheritdoc}
     */
    protected function loadUser($username, Entry $entry)
    {
        $user = parent::loadUser($username, $entry);
        return new LdapUser($username, $user->getPassword(), $user->getRoles(), $entry);
    }
}

2.LDAP用户

    <?php
    namespace YourAppBundle\Security\User;
    use Symfony\Component\Security\Core\User\UserInterface;
    use Symfony\Component\Ldap\Entry;
    class LdapUser implements UserInterface
    {
        const LDAP_KEY_DISPLAY_NAME = 'displayName';
        const LDAP_KEY_MAIL = 'mail';
        protected $username;
        protected $password;
        protected $roles;
        protected $ldapEntry;
        protected $displayName;
        protected $eMail;
        public function __construct($username, $password, array $roles, Entry $ldapEntry)
        {
            if ('' === $username || null === $username) {
                throw new \InvalidArgumentException('The username cannot be empty.');
            }
            $this->username    = $username;
            $this->password    = $password;
            $this->roles       = $roles;
            $this->ldapEntry   = $ldapEntry;
            $this->displayName = $this->extractSingleValueByKeyFromEntry(
                $ldapEntry,
                self::LDAP_KEY_DISPLAY_NAME,
                $username
            );
            $this->eMail       = $this->extractSingleValueByKeyFromEntry($ldapEntry, self::LDAP_KEY_MAIL);
        }
        public function __toString()
        {
            return (string) $this->getUsername();
        }
        public function getDisplayName()
        {
            return $this->displayName;
        }
        /**
         * @return Entry
         */
        public function getLdapEntry()
        {
            return $this->ldapEntry;
        }
        /**
         * {@inheritdoc}
         */
        public function getRoles()
        {
            return $this->roles;
        }
        /**
         * {@inheritdoc}
         */
        public function getPassword()
        {
            return $this->password;
        }
        /**
         * {@inheritdoc}
         */
        public function getSalt()
        {
        }
        /**
         * {@inheritdoc}
         */
        public function getUsername()
        {
            return $this->username;
        }
        /**
         * {@inheritdoc}
         */
        public function eraseCredentials()
        {
        }
        /**
         * Extracts single value from entry's array value by key.
         *
         * @param Entry       $entry        Ldap entry
         * @param string      $key          Key
         * @param null|string $defaultValue Default value
         *
         * @return string|null
         */
        protected function extractSingleValueByKeyFromEntry(Entry $entry, $key, $defaultValue = null)
        {
            $value = $this->extractFromLdapEntry($entry, $key, $defaultValue);
            return is_array($value) && isset($value[0]) ? $value[0] : $defaultValue;
        }
        /**
         * Extracts value from entry by key.
         *
         * @param Entry  $entry        Ldap entry
         * @param string $key          Key
         * @param mixed  $defaultValue Default value
         *
         * @return array|mixed
         */
        protected function extractFromLdapEntry(Entry $entry, $key, $defaultValue = null)
        {
            if (!$entry->hasAttribute($key)) {
                return $defaultValue;
            }
            return $entry->getAttribute($key);
        }
    }

3.Services.yml

我们需要定义我们新创建的ldap用户提供者服务

    services:

        ...
    app.ldap:
            class: Symfony\Component\Ldap\Ldap
            factory: ['Symfony\Component\Ldap\Ldap', 'create']
            arguments:
                - 'ext_ldap'
                - host: '%ldap_host%'
    app.ext_ldap_user_provider:
                class: YourAppBundle\Security\User\LdapUserProvider
                arguments:
                    - '@app.ldap'               # LDAP component instance
                    - '%ldap_base_dn%'          # Base dn
                    - '%ldap_search_dn%'        # Search dn
                    - '%ldap_search_password%'  # Search user password
                    - ['ROLE_SUPER_ADMIN']      # Roles
                    - '%ldap_uid_key%'          # LDAP uid key
                    - '%ldap_filter%'           # filter

4.Security.yml

这只是我们提供程序的一个示例用法—“ / ui”将通过LDAP保护。

security:
     encoders:

     ...
     YourAppBundle\Security\User\LdapUser:
            algorithm: bcrypt
            cost: 12
     providers:

     ...
        ldap_users:
            id: app.ext_ldap_user_provider
...
     firewalls:
         frontend:
            anonymous: ~
            provider: ldap_users
            form_login_ldap:
                service: app.ldap
                dn_string: '%ldap_dn_string%'
                login_path: front-login
                check_path: front-login
                default_target_path: /ui
            logout:
                path: front-logout
                target: front-login
     access_control:

        ...
        - { path: ^/ui/logout, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/ui/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/ui, roles: IS_AUTHENTICATED_FULLY }