我正在尝试将Symfony 4.3.6应用程序升级到v4.4。
该应用使用oauth2-client-bundle通过Keycloak对用户进行身份验证。因此,用户永远不会保留在数据库中。 这是安全性配置:
security:
providers:
oauth:
id: knpu.oauth2.user_provider
firewalls:
main:
logout:
path: app.logout
anonymous: true
guard:
authenticators:
- App\Security\KeycloakAuthenticator
access_control:
- { path: ^/connect, roles: IS_AUTHENTICATED_ANONYMOUSLY }
-
path: ^/
allow_if: "'127.0.0.1' == request.getClientIp() or is_granted('IS_AUTHENTICATED_FULLY')"
这是KeycloakAuthenticator
服务:
<?php
namespace App\Security;
use App\Entity\User; // extends KnpU\OAuth2ClientBundle\Security\User\OAuthUser
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use KnpU\OAuth2ClientBundle\Client\Provider\KeycloakClient;
use KnpU\OAuth2ClientBundle\Security\Authenticator\SocialAuthenticator;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
class KeycloakAuthenticator extends SocialAuthenticator
{
private $clientRegistry;
private $router;
public function __construct(ClientRegistry $clientRegistry, RouterInterface $router)
{
$this->clientRegistry = $clientRegistry;
$this->router = $router;
}
public function supports(Request $request)
{
return 'connect_keycloak_check' === $request->attributes->get('_route');
}
public function getCredentials(Request $request)
{
return $this->fetchAccessToken($this->getKeycloakClient());
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$keycloakUser = $this->getKeycloakClient()->fetchUserFromToken($credentials);
$user = new User($keycloakUser->getName(), ['IS_AUTHENTICATED_FULLY', 'ROLE_USER']);
$user->setEmail($keycloakUser->getEmail())
->setName($keycloakUser->getName())
->setLocale($keycloakUser->toArray()['locale'] ?? 'fr')
;
return $user;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
// On success, let the request continue
return null;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$message = strtr($exception->getMessageKey(), $exception->getMessageData());
return new Response($message, Response::HTTP_FORBIDDEN);
}
public function start(Request $request, AuthenticationException $authException = null)
{
return new RedirectResponse($this->router->generate('app.keycloak_start'), Response::HTTP_TEMPORARY_REDIRECT);
}
private function getKeycloakClient(): KeycloakClient
{
return $this->clientRegistry->getClient('keycloak');
}
}
根据official documentation开发了功能测试:
public function testHomePage()
{
$client = static::createClient();
$session = $client->getContainer()->get('session');
$firewallName = 'main';
$token = new PostAuthenticationGuardToken(new User('foo', ['ROLE_USER']), $firewallName, $roles);
$session->set('_security_'.$firewallName, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$client->getCookieJar()->set($cookie);
$client->request('GET', '/');
$this->assertTrue($client->getResponse()->isSuccessful());
}
直到现在,测试通过,一切都很好。
但是由于我将Symfony升级到4.4,所以方法ControllerTrait::getUser()
返回null
,并且在运行功能测试时遇到以下错误:
错误:在null上调用成员函数getUsername()
除了调用$this->getUser()
时照常获得当前用户外,我都是这样。
我尝试在security.token_storage
中手动设置令牌,但错误仍然存在。
我还尝试通过删除“ security.yaml”的"'127.0.0.1' == request.getClientIp()
部分中的allow_if
部分来强制进行身份验证,现在响应为“ 307临时重定向到Keycloak”服务。
在这两个版本之间,$this->getUser()
的行为是否发生了变化?
谢谢您的帮助