首页 > 解决方案 > 为什么没有调用回调标识符?

问题描述

我正在尝试实现将 Kerberos 身份验证与 CakePHP4 中的本地用户数据库匹配。所以我安装了 CakePHP 4 和 Authentication plugin 2.0。由于 Kerberos 身份验证由我们的 IIS WebServer 管理,我唯一要做的就是检查我的 webapp 是否知道经过身份验证的用户。

回调身份验证应该让我实现这样的事情,对吧?所以我把这个函数放在 Application.php 中:

<?php
    public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
    {
        $service = new AuthenticationService();
    
        // Define where users should be redirected to when they are not authenticated
        $service->setConfig([
            'unauthenticatedRedirect' => '/users/login',
            'queryParam' => 'redirect',
        ]);
    
        // Load the authenticators. Session should be first.
        $service->loadAuthenticator('Authentication.Session');
    
        $service->loadIdentifier('Authentication.Callback', [
            'callback' => function($data) {
                // do identifier logic
                if (empty($_SERVER['REMOTE_USER'])) {
                    return new Result(
                        null,
                        Result::FAILURE_OTHER,
                        ['message' => 'Unknown user.']
                    );
                } else {
                    // On vérifie que l'utilisateur est autorisé à utiliser cette application
                    $users = TableRegistry::getTableLocator()->get('Users');
                    $remoteUserNoDomain = str_replace("DOMAIN\\", "", $_SERVER['REMOTE_USER']);
    
                    $result = $users->find()
                        ->where(['username' => $remoteUserNoDomain]);
                    
                    if ($result) {
                        return new Result($result, Result::SUCCESS);
                    }
            
                    return new Result(
                        null,
                        Result::FAILURE_OTHER,
                        ['message' => 'Removed user.']
                    );
                }
                
                return null;
            }
        ]);
    
        return $service;
    }

但到目前为止,它似乎不起作用,就像它根本不会调用回调函数一样。我试图放置一些调试代码,退出......没有任何效果。

标签: authenticationcakephpkerberoscakephp-4.x

解决方案


我假设您还完成了所有其他必需的身份验证配置,即加载插件、添加身份验证中间件等!?

https://book.cakephp.org/authentication/2/en/index.html

也就是说,标识符本身不会做任何工作,它们是由身份验证器触发的,以防它们真正需要它们。您只Session加载了身份验证器,在其默认配置中不使用标识符,但即使您将其配置为使用标识符(通过将其identify选项设置为true),它也只会在已经存在身份时使用它们会话,则标识符将用于验证该身份。

https://github.com/cakephp/authentication/blob/2.3.0/src/Authenticator/SessionAuthenticator.php#L52

我对 Kerberos 身份验证不熟悉,但如果它预先填充$_SERVER['REMOTE_USER'](顺便说一句,从不直接访问 CakePHP 中的超全局变量,它只会在以后造成麻烦),那么您需要的是自定义身份验证器。然后,您可以重新使用 ORM 访问部分的密码标识符,因为它允许在不检查密码的情况下查找某些内容(很奇怪,给定它的名称)。

基于您的代码段的快速而肮脏的示例:

// src/Authenticator/KerberosAuthenticator.php

namespace App\Authenticator;

use Authentication\Authenticator\AbstractAuthenticator;
use Authentication\Authenticator\Result;
use Authentication\Authenticator\ResultInterface;
use Psr\Http\Message\ServerRequestInterface;

class KerberosAuthenticator extends AbstractAuthenticator
{
    public function authenticate(ServerRequestInterface $request): ResultInterface
    {
        $server = $request->getServerParams();

        if (empty($server['REMOTE_USER'])) {
            return new Result(null, Result::FAILURE_CREDENTIALS_MISSING);
        }

        $remoteUserNoDomain = str_replace("DOMAIN\\", "", $server['REMOTE_USER']);
        $user = $this->_identifier->identify(['username' => $remoteUserNoDomain]);

        if (empty($user)) {
            return new Result(
                null, 
                Result::FAILURE_IDENTITY_NOT_FOUND, 
                $this->_identifier->getErrors()
            );
        }

        return new Result($user, Result::SUCCESS);
    }
}

您的服务验证器/标识符设置将如下所示:

$service->loadAuthenticator('Authentication.Session');
$service->loadAuthenticator('Kerberos');

$service->loadIdentifier('Authentication.Password');

不确定您是否真的想像那样使用会话身份验证器,即您是否只想在每个会话中识别一次远程用户。


推荐阅读