jmleroy/ldap-bundle

Symfony 3的LDAP Bundle(向后兼容)

v2.4.10 2019-03-29 14:55 UTC

README

LdapBundle提供了一种不使用Apache的mod_ldap进行LDAP身份验证的方法。该Bundle依赖于PHP的LDAP扩展以及用于身份验证的用户表单。LdapBundle还可以通过检索在LDAP中定义的用户角色来进行授权。

致谢

此Bundle最初由Boris Morel创建,然后由Subramanya Vajiraya分叉。由于原始维护者已停止维护此Bundle,并且可能最后的分叉者也放弃了它(最后更新于2017年),并且我需要修复它,因此我既提交了拉取请求,也自己分叉了它。任何人都可以自由使用此Bundle并按需修改它。我将努力保持此Bundle的最新状态。如果您成功地更新了项目,请提交拉取请求,我将很高兴审查并合并它。

安装

  1. 使用composer下载
  2. 启用Bundle
  3. 在security.yml中配置LdapBundle
  4. 导入LdapBundle路由
  5. 实现注销
  6. 使用链式提供者
  7. 订阅PRE_BIND事件
  8. 订阅POST_BIND事件

获取Bundle

Composer

在您的项目的composer.json中添加LdapBundle

{
    "require": {
        "jmleroy/ldap-bundle": "dev-master"
    }
}

composer require jmleroy/ldap-bundle

启用Bundle

<?php
// app/AppKernel.php

public function registerBundles()
{
    $bundles = array(
        // ...
        new IMAG\LdapBundle\IMAGLdapBundle(),
    );
}

配置security.yml

注意

示例security.yml文件位于Bundle中的./Resources/Docs/security.yml

# ./IMAG/LdapBundle/Resources/config/security.yml

security:
  firewalls:
    restricted_area:
      pattern:          ^/
      anonymous:        ~
      provider:         ldap
      imag_ldap:        ~
      # alternative configuration
      # imag_ldap:
      #   login_path:   /ninja/login
      logout:
        path:           /logout
        target:         /

  providers:
    ldap:
      id: imag_ldap.security.user.provider
                
  encoders:
    IMAG\LdapBundle\User\LdapUser: plaintext

  access_control:
    - { path: ^/login,          roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/,               roles: IS_AUTHENTICATED_FULLY }

imag_ldap:
  client:
    host: your.host.foo
    port: 389
#    version: 3 # Optional
#    username: foo # Optional
#    password: bar # Optional
#    network_timeout: 10 # Optional
#    referrals_enabled: true # Optional
#    bind_username_before: true # Optional
#    skip_roles: false # Optional

  user:
    base_dn: ou=people,dc=host,dc=foo
#    filter: (&(foo=bar)(ObjectClass=Person)) #Optional
    name_attribute: uid
  role:
    base_dn: ou=group, dc=host, dc=foo
#    filter: (ou=group) #Optional
    name_attribute: cn
    user_attribute: member
    user_id: [ dn or username ]
    
#  user_class: IMAG\LdapBundle\User\LdapUser # Optional

您应该配置imag_ldap部分下的参数以匹配您的环境。

注意

如果未设置,则可选参数具有默认值。您可以通过将参数设置为NULL来禁用默认值。

# app/config/security.yml
imag_ldap:
  # ...
  role:
    # ...
    filter: NULL

导入路由

# app/config/routing.yml

imag_ldap:
  resource: "@IMAGLdapBundle/Resources/config/routing.yml"

实现登录

只需将隐藏标签添加到登录表单中,并将id设置为ldap_authenticate

<input type="hidden" name="_csrf_token" value="{{ csrf_token('ldap_authenticate') }}">

实现注销

只需创建一个具有注销目标的链接。

<a href="{{ path('logout') }}">Logout</a>

注意

您可以参考官方的Symfony文档:https://symfony.com.cn/doc/current/book/security.html#logging-out

链式提供者

您还可以将登录表单与其他提供者链式,例如数据库提供者、内存提供者等。

# app/config/security.yml
security:
    firewalls:
        secured_area:
            pattern: ^/
            anonymous: ~
            imag_ldap:
                provider: multiples
            logout:
                path: logout
    providers:
        multiples:
            chain:
                providers: [ldap, db]          
        ldap:
            id: imag_ldap.security.user.provider
        db:
            entity: { class: FQDN\User }

注意

如果您设置了配置选项bind_username_before: true,则必须在最后位置将提供者与LDAP提供者链式。

# app/config/security.yml

providers: [db, ldap]          

订阅PRE_BIND事件

PRE_BIND在用户通过LDAP进行身份验证之前触发。在这里,您可以编写一个监听器在用户绑定/验证到LDAP之前执行自己的逻辑。例如,添加您自己的角色或对您的应用程序进行其他身份验证/授权检查。

如果您想在监听器中中断身份验证过程,则抛出异常。

示例监听器

<service id="ldap.listener" class="Acme\HelloBundle\EventListener\LdapSecuritySubscriber">
    <tag name="kernel.event_subscriber" />
</service>

示例

<?php

namespace Acme\HelloBundle\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use IMAG\LdapBundle\Event\LdapUserEvent;

/**
 * Performs logic before the user is found to LDAP
 */
class LdapSecuritySubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            \IMAG\LdapBundle\Event\LdapEvents::PRE_BIND => 'onPreBind',
        );
    }

    /**
     * Modifies the User before binding data from LDAP
     *
     * @param \IMAG\LdapBundle\Event\LdapUserEvent $event
     */
    public function onPreBind(LdapUserEvent $event)
    {
        $user = $event->getUser();
        $config = $this->appContext->getConfig();

        $ldapConf = $config['ldap'];

        if (!in_array($user->getUsername(), $ldapConf['allowed'])) {
            throw new \Exception(sprintf('LDAP user %s not allowed', $user->getUsername()));
        }

		$user->addRole('ROLE_LDAP');
        $event->setUser($user);
    }
}

订阅POST_BIND事件

POST_BIND在用户通过LDAP进行身份验证之后触发。您可以使用它与PRE_BIND完全相同的方式。

注意

然而,每次页面刷新时,Symfony都会在使用的提供者中调用refreshUser方法,并且不会触发这些事件(PRE_BIND和POST_BIND)。如果您想覆盖用户(例如,如凭据、角色等),则必须创建一个新的提供者并重写此方法。