我正在尝试在 CakePHP4 中实现 Kerberos 身份验证与本地用户数据库的匹配。所以我安装了 CakePHP 4 和身份验证插件 2.0。由于 Kerberos 身份验证由我们的 IIS Web 服务器管理,因此我唯一要做的就是检查我的 web 应用程序是否知道经过身份验证的用户。
回调认证应该让我实现这样的东西,对吧? 所以我把这个函数放在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;
}
但是到目前为止,它似乎不起作用,就像它根本不会调用回调函数一样。我尝试添加一些调试代码,然后退出...没有任何效果。
我假设您还完成了身份验证工作所需的所有其他配置,即加载插件、添加身份验证中间件等!?
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');
不确定您是否真的想使用这样的会话身份验证器,即您是否只想在每个会话中识别远程用户一次。