dongliang1654 2019-03-15 14:20
浏览 105
已采纳

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

I'm trying to grant roles to a user according to their LDAP dn when they log in through the LDAP. To do that, I'd like to override the loadUser method from Symfony\Component\Security\Core\User\LdapUserProvider, but I don't really know how to proceed as, if I understand correctly (I'm quite new at using Symfony :p), it's not a service, but part of one? So, is there a way to override that method easily, or do I need to redefine the whole Ldap service?

What I've tried is:

// 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'));
    }
}

But of course it doesn't work and I don't get the ROLE_TEST role.

Thanks by advance!

  • 写回答

1条回答 默认 最新

  • donglan6777 2019-03-15 14:51
    关注

    You can use this tutorial:

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

    and you should create a LdapUser class that implements UserInterface

    1.LDAP user provider

    <?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 user

        <?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

    we need to define our newly created ldap user provider service

        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

    Here is just an example usage of our provider — the “/ui” will be secured with 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 }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化