cakephp使用ldap进行身份验证并与本地用户匹配(或创建一个)

时间:2019-08-29 02:34:15

标签: php authentication cakephp ldap cakephp-3.x

我正在尝试使用新的cakephp/authentication插件在cakephp 3.8上配置ldap身份验证,并且不确定如何将经过身份验证的ldap用户与本地实体匹配。

我的配置紧跟documentation,并且可以使用完整的here

在我的Application.phpApplication中实现了AuthenticationServiceProviderInterfaceAuthorizationServiceProviderInterface

public function getAuthenticationService(ServerRequestInterface $request, 
                                         ResponseInterface $response)
{
    $service = new AuthenticationService();
    $service->loadIdentifier('Authentication.Password', [...]),
    $service->loadIdentifier('Authentication.Ldap', [
        'fields' => [
           'username' => 'username',
           'password' => 'password'
        ],
        'host' => 'ldap.forumsys.com',
        'port' => '389',
        'bindDN' => function($username) {
                return 'uid='.$username.',DC=example,DC=com';
            },
        'options' => [LDAP_OPT_PROTOCOL_VERSION => 3]
    ]);

    $service->loadAuthenticator('Authentication.Session');
    $service->loadAuthenticator('Authentication.Form', [
            'fields' => [
                'username' => 'email', 
                'password' => 'password'
             ],
            'loginUrl' => '/users/login'
    ]);

    return $service;
}

在我的中间件中,我正在尝试用授权内容装饰身份。使用常规本地系统进行身份验证时,$identityApp\Model\Entity\User,但是使用ldap用户登录时,它是Authentication\Identity

所以当我打电话给setAuthorization

'identityDecorator' => function (AuthorizationServiceInterface $authorization, 
                                 ArrayAccess $identity) {
    $identity->setAuthorization($authorization);
}

由于Call to undefined method Authentication\Identity::setAuthorization()中的所有内容都是

,因此失败并显示$identity
object(Authentication\Identity) {

    'config' => [
        'fieldMap' => [
            'id' => 'id'
        ]
    ],
    'data' => object(ArrayObject) {
        username => 'einstein'
    }

}

我如何将经过身份验证的ldap用户与他们的本地用户匹配,并从Authentication\Identity转换为App\Model\Entity\User

最终目标是还可以从ldap数据(如果不存在)中选择生成本地用户。


中间件尝试

Application.php

public function middleware($middlewareQueue)
{
    ...

    $middlewareQueue->add($authentication);
    $middlewareQueue->add($ldap_matcher);
    $middlewareQueue->add($authorization);

    return $middlewareQueue;
}

LdapMatcherMiddleware.php

class LdapMatcherMiddleware
{
    public function __invoke(ServerRequestInterface $request, 
                             ResponseInterface $response, $next)
    {
        $identity = $request->getAttribute('identity');

        if ($identity !== null) {
            $identity = $this->buildIdentity($identity);
            $request = $request->withAttribute('identity', $identity);
        }

        $response = $next($request, $response);

        return $response;
    }

    public function buildIdentity($identity)
    {
        $Users = TableRegistry::getTableLocator()->get('Users');

        $username = $identity->getOriginalData()['username'];
        $user = $Users->find()->where(['username' => $username])->first();

        if (is_null($identity)) {
            $user = $this->createLocalUserFromLdap($identity);
        }

        return $user;
    }

    public function createLocalUserFromLdap($identity)
    {
        $Users = TableRegistry::getTableLocator()->get('Users');

        $user = $Users->newEntity([
            'username' => $identity->getOriginalData()['username']
        ]);

        $Users->save($user);

        return $user;
    }
}

1 个答案:

答案 0 :(得分:1)

  

我如何将经过身份验证的ldap用户与其本地对应者匹配,并从Authentication \ Identity转换为App \ Model \ Entity \ User?

我将在身份验证中间件之后添加另一个中间件,并在那里执行该步骤。

$users = TableRegistry::getTableLocator()->get('Users');
$entity = $users->newEntity($identity->getOriginalData());

然后执行此实体的授权所需要做的一切。

  

最终目标是还可以从ldap数据(如果不存在)中选择生成本地用户。

只需在某个地方实现您的逻辑并以与上述身份相同的方式获取实体即可。

$users = TableRegistry::getTableLocator()->get('Users');
$entity = $users->newEntity($identity->getOriginalData());
// Check if it exists inside this method and if not just create it
$users->createLocalUserFromLDAP($entity);