Symfony 4.0
Este processo não mudou do symfony 3 para 4, mas aqui está um exemplo usando o recém-recomendado AbstractController. Os serviços security.token_storage
e os session
são registrados no getSubscribedServices
método pai , portanto, você não precisa adicioná-los ao seu controlador.
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use YourNameSpace\UserBundle\Entity\User;
class LoginController extends AbstractController{
public function registerAction()
{
$user = //Handle getting or creating the user entity likely with a posted form
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->container->get('security.token_storage')->setToken($token);
$this->container->get('session')->set('_security_main', serialize($token));
// The user is now logged in, you can redirect or do whatever.
}
}
Symfony 2.6.x - Symfony 3.0.x
A partir do symfony 2.6 security.context
está obsoleto em favor de security.token_storage
. O controlador agora pode ser simplesmente:
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use YourNameSpace\UserBundle\Entity\User;
class LoginController extends Controller{
public function registerAction()
{
$user = //Handle getting or creating the user entity likely with a posted form
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.token_storage')->setToken($token);
$this->get('session')->set('_security_main', serialize($token));
}
}
Embora esteja obsoleto, você ainda pode usar security.context
, pois foi feito para ser compatível com versões anteriores. Esteja pronto para atualizá-lo para Symfony 3
Você pode ler mais sobre as mudanças 2.6 para segurança aqui: https://github.com/symfony/symfony/blob/2.6/UPGRADE-2.6.md
Symfony 2.3.x
Para conseguir isso no symfony 2.3, você não pode mais apenas definir o token no contexto de segurança. Você também precisa salvar o token na sessão.
Presumindo um arquivo de segurança com um firewall como:
// app/config/security.yml
security:
firewalls:
main:
//firewall settings here
E uma ação de controle semelhante também:
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use YourNameSpace\UserBundle\Entity\User;
class LoginController extends Controller{
public function registerAction()
{
$user = //Handle getting or creating the user entity likely with a posted form
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.context')->setToken($token);
$this->get('session')->set('_security_main',serialize($token));
//Now you can redirect where ever you need and the user will be logged in
}
}
Para a criação do token, você desejará criar um UsernamePasswordToken
, que aceita 4 parâmetros: Entidade do usuário, Credenciais do usuário, Nome do firewall, Funções do usuário. Você não precisa fornecer as credenciais do usuário para que o token seja válido.
Não tenho 100% de certeza de que definir o token no security.context
seja necessário se você for redirecionar imediatamente. Mas não parece doer, então eu o deixei.
Em seguida, a parte importante, definir a variável de sessão. A convenção variáveis nomeando é _security_
seguido pelo seu nome firewall, neste caso, main
a tomada_security_main
$this->get('session')->set('_security_main', serialize($token));
. Obrigado, @Chausser!main
E você for autenticado com outro firewall chamadoadmin
(já que você está se passando por usuário), uma coisa estranha acontece: o_security_admin
obtém oUsernamePasswordToken
com o usuário fornecido, ou seja, você é "desconectado" do seuadmin
firewall. Alguma ideia de como manter o token para o firewall "admin"?setToken(..)
no mesmo firewall de destino ou sem estar autenticado ainda.Descobri este, finalmente.
Após o registro do usuário, você deve ter acesso a uma instância de objeto de tudo o que você definiu como sua entidade de usuário na configuração do seu provedor. A solução é criar um novo token com essa entidade de usuário e passá-lo para o contexto de segurança. Aqui está um exemplo baseado em minha configuração:
RegistrationController.php:
Onde
main
está o nome do firewall do seu aplicativo (obrigado, @Joe). Isso é realmente tudo que há para fazer; o sistema agora considera seu usuário totalmente logado como o usuário que acabou de criar.EDIT: Com o comentário de @Miquel, atualizei o exemplo de código do controlador para incluir uma função padrão sensata para um novo usuário (embora, obviamente, isso possa ser ajustado de acordo com as necessidades específicas do seu aplicativo).
fonte
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
Se você tiver um objeto UserInterface (e esse deve ser o caso na maioria das vezes), você pode querer usar a função getRoles que ele implementa para o último argumento. Portanto, se você criar uma função logUser, ela deve se parecer com:
fonte
Estou usando Symfony 2.2 e minha experiência foi um pouco diferente da da Problemática , então esta é uma versão combinada de todas as informações desta questão mais algumas das minhas.
Acho que Joe está errado sobre o valor de
$providerKey
, o terceiro parâmetro doUsernamePasswordToken
construtor. Supõe-se que seja a chave de um provedor de autenticação (não do usuário). É usado pelo sistema de autenticação para distinguir entre tokens criados para diferentes provedores. Qualquer provedor descendente deUserAuthenticationProvider
autenticará apenas tokens cuja chave de provedor corresponda à sua. Por exemplo, oUsernamePasswordFormAuthenticationListener
define a chave do token que ele cria para corresponder ao seu correspondenteDaoAuthenticationProvider
. Isso permite que um único firewall tenha vários provedores de nome de usuário + senha sem que eles se atropelem. Portanto, precisamos escolher uma chave que não entre em conflito com nenhum outro provedor. Eu uso'new_user'
.Tenho alguns sistemas em outras partes do meu aplicativo que dependem do evento de sucesso da autenticação e que não são acionados apenas definindo o token no contexto. Tive que obter o
EventDispatcher
do contêiner e disparar o evento manualmente. Decidi também não disparar um evento de login interativo porque estamos autenticando o usuário implicitamente, não em resposta a uma solicitação de login explícita.Observe que o uso de
$this->get( .. )
assume que o snippet está em um método de controlador. Se estiver usando o código em outro lugar, você terá que alterá-lo para chamarContainerInterface::get( ... )
de uma forma apropriada ao ambiente. Acontece que minhas entidades de usuário implementamUserInterface
para que eu possa usá-las diretamente com o token. Caso contrário, você terá que encontrar uma maneira de convertê-los paraUserInterface
instâncias.Esse código funciona, mas eu sinto que ele está hackeando a arquitetura de autenticação do Symfony ao invés de trabalhar com ela. Provavelmente seria mais correto implementar um novo provedor de autenticação com sua própria classe de token em vez de sequestrar o
UsernamePasswordToken
. Além disso, usar um provedor adequado significaria que os eventos foram gerenciados para você.fonte
Caso alguém tenha a mesma pergunta que me fez voltar a aqui:
Chamando
afeta apenas a corrente
security.context
para a rota usada.Ou seja, você só pode fazer login de um usuário a partir de uma url sob o controle do firewall.
(Adicione uma exceção para a rota, se necessário -
IS_AUTHENTICATED_ANONYMOUSLY
)fonte
Com Symfony 4.4, você pode simplesmente fazer o seguinte em seu método de controlador (veja na documentação do Symfony: https://symfony.com/doc/current/security/guard_authentication.html#manually-authenticating-a-user ):
Uma coisa importante, certifique-se de que seu firewall não esteja configurado para
lazy
. Se for, o token nunca será armazenado na sessão e você nunca fará login.fonte
Como Problemático já mencionado aqui, este parâmetro $ providerKey indescritível nada mais é do que o nome de sua regra de firewall, 'foobar' no caso do exemplo abaixo.
fonte
blablabla
como terceiro parâmetro para UsernamePasswordToken, também funcionará? o que esse parâmetro significa?Tentei todas as respostas aqui e nenhuma funcionou. A única maneira de autenticar meus usuários em um controlador é fazendo uma sub-solicitação e redirecionando. Aqui está meu código, estou usando silex, mas você pode adaptá-lo facilmente para o symfony2:
fonte
No Symfony versão 2.8.11 (provavelmente funcionando para versões mais antigas e mais recentes), se você usar FOSUserBundle, simplesmente faça o seguinte:
Não há necessidade de despachar o evento, como já vi em outras soluções.
inspirado em FOS \ UserBundle \ Controller \ RegistrationController :: authenticateUser
(da versão composer.json FOSUserBundle: "friendsofsymfony / user-bundle": "~ 1,3")
fonte