Documentação do Symfony2
Renderizada do repositório symfony-docs-pt-BR no Github
Parte do processo de autenticação padrão do Symfony depende de “providers de usuário”. Quando um usuário submete um nome de usuário e senha, a camada de autenticação solicita ao provider de usuário configurado para retornar um objeto de usuário para um determinado nome de usuário. Em seguida, o Symfony verifica se a senha deste usuário está correta e gera um token de segurança para que o usuário permaneça autenticado durante a sessão atual. O Symfony vem com os providers de usuário “in_memory” e “entity” prontos para uso. Neste artigo, você vai aprender como criar o seu próprio provider de usuário, que pode ser útil se os usuários são acessados através de um banco de dados personalizado, um arquivo ou - como mostrado neste exemplo - um serviço web.
Em primeiro lugar, independentemente de onde os seus dados de usuário estão vindo, você vai precisar criar uma classe User que representa esses dados. No entando, a classe User pode parecer com o que você quiser e conter quaisquer dados. O único requisito é que a classe implemente Symfony\Component\Security\Core\User\UserInterface. Os métodos dessa interface devem ser definidos na classe de usuário personalizada: :method:`Symfony\\Component\\Security\\Core\\User\\UserInterface::getRoles`, :method:`Symfony\\Component\\Security\\Core\\User\\UserInterface::getPassword`, :method:`Symfony\\Component\\Security\\Core\\User\\UserInterface::getSalt`, :method:`Symfony\\Component\\Security\\Core\\User\\UserInterface::getUsername`, :method:`Symfony\\Component\\Security\\Core\\User\\UserInterface::eraseCredentials`. Também pode ser útil implementar a interface Symfony\Component\Security\Core\User\EquatableInterface, a qual define um método para verificar se o usuário é igual ao usuário atual. Essa interface requer um método :method:`Symfony\\Component\\Security\\Core\\User\\EquatableInterface::isEqualTo` .
Vamos ver isso na prática:
// src/Acme/WebserviceUserBundle/Security/User/WebserviceUser.php
namespace Acme\WebserviceUserBundle\Security\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\EquatableInterface;
class WebserviceUser implements UserInterface, EquatableInterface
{
private $username;
private $password;
private $salt;
private $roles;
public function __construct($username, $password, $salt, array $roles)
{
$this->username = $username;
$this->password = $password;
$this->salt = $salt;
$this->roles = $roles;
}
public function getRoles()
{
return $this->roles;
}
public function getPassword()
{
return $this->password;
}
public function getSalt()
{
return $this->salt;
}
public function getUsername()
{
return $this->username;
}
public function eraseCredentials()
{
}
public function isEqualTo(UserInterface $user)
{
if (!$user instanceof WebserviceUser) {
return false;
}
if ($this->password !== $user->getPassword()) {
return false;
}
if ($this->getSalt() !== $user->getSalt()) {
return false;
}
if ($this->username !== $user->getUsername()) {
return false;
}
return true;
}
}
Se você tiver mais informações sobre seus usuários - como um “primeiro nome” - então você pode adicionar um campo firstName para guardar esse dado.
Agora que você tem uma classe User, você vai criar um provider de usuário, que irá pegar informações de usuário de algum serviço web, criar um objeto WebserviceUser e popular ele com os dados.
O provider de usuário é apenas uma classe PHP que deve implementar a Symfony\Component\Security\Core\User\UserProviderInterface, que requer a definição de três métodos: loadUserByUsername($username), refreshUser(UserInterface $user) e supportsClass($class). Para mais detalhes, consulte Symfony\Component\Security\Core\User\UserProviderInterface.
Aqui está um exemplo de como isso pode parecer:
// src/Acme/WebserviceUserBundle/Security/User/WebserviceUserProvider.php
namespace Acme\WebserviceUserBundle\Security\User;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
class WebserviceUserProvider implements UserProviderInterface
{
public function loadUserByUsername($username)
{
// make a call to your webservice here
$userData = ...
// pretend it returns an array on success, false if there is no user
if ($userData) {
$password = '...';
// ...
return new WebserviceUser($username, $password, $salt, $roles);
}
throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
}
public function refreshUser(UserInterface $user)
{
if (!$user instanceof WebserviceUser) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $class === 'Acme\WebserviceUserBundle\Security\User\WebserviceUser';
}
}
Agora você tornará o provider de usuário disponível como um serviço:
Tip
A verdadeira implementação do provider de usuário provavelmente terá algumas dependências, opções de configuração ou outros serviços. Adicione eles como argumentos na definição de serviço.
Note
Certifique-se que o arquivo de serviços está sendo importado. Veja Importando configuração com imports para mais detalhes.
Tudo será combinado em sua configuração de segurança. Adicione o provider de usuário na lista de providers na seção “security”. Escolha um nome para o provider de usuário (por exemplo, “webservice”) e mencione o id do serviço que você acabou de definir.
O Symfony também precisa saber como codificar as senhas que são fornecidas no site pelos usuários, por exemplo, através do preenchimento de um formulário de login. Você pode fazer isso adicionando uma linha na seção “encoders” da sua configuração de segurança:
O valor aqui deve corresponder porém com as senhas que foram originalmente codificadas ao criar os seus usuários (no entanto os usuários foram criados). Quando um usuário submete a sua senha, o salt é acrescentado ao valor da senha e então são codificados usando este algoritmo antes de ser comparada com o hash da senha retornado pelo seu método getPassword(). Além disso, dependendo das suas opções, a senha pode ser codificada várias vezes e codificada para base64.