Implemente seu próprio SecurityController
Recentemente, escrevi um artigo para minha empresa sobre como gerenciar usuários e sua autenticação nativamente usando o Symfony2 Core e, portanto, sem o FOSUserBundle. Na sequência deste já rico primeiro artigo, queria descrever uma segunda parte igualmente útil que nos permitirá configurar rapidamente as funções essenciais, nomeadamente, redefinir a sua palavra-passe, alterar a sua palavra-passe, validar a sua conta ou mesmo registar-se. Ações igualmente essenciais quando você tem um sistema gerenciando usuários.
Configurar um SecurityController
Primeiramente, se você ainda não seguiu o primeiro tutorial de como configurar o gerenciamento de usuários, aconselho a dar uma olhada. Se você seguiu a solução, logicamente deve ter um SecurityController ou outra coisa. No meu caso, tenho apenas três métodos, dos quais apenas um é realmente utilizável.
- loginAction
Este método conecta um usuário. - checkAction
Este método simplesmente permite que você declare uma rota para o firewall, permitindo que um usuário se conecte no lado do servidor. - logoutAção
Este método é usado para declarar uma rota para o firewall permitindo que um usuário seja desconectado.
Abra nossa plataforma para novos usuários
Seria particularmente interessante se nossos usuários pudessem se conectar e, portanto, se registrar com antecedência.
Primeiramente, geramos o formulário com as informações que você deseja solicitar ao seu usuário.
Em relação ao formulário que você usará para registrar seu usuário, saiba que o campo " senha não deve estar em seu formulário. No entanto, você precisará adicionar dois campos " não mapeado para que a senha desejada seja digitada duas vezes.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/ **
* @Método({"PEGAR"})
* @Rota(“/registro”, nome=”registro”)
* @Seguro(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modelo()
*/
público função cadastre-se()
{
$formulário = $ This->criarFormulário(novo UserType(UserType::REGISTER), novo Do utilizador());
retorno ordem(
"forma" => $form->createView(),
);
}
|
Então, é quando seu usuário voltar com o formulário preenchido que teremos que registrá-lo ou rejeitar seu arquivo :p
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/ **
* @Método({"PUBLICAR"})
* @Rota("/registro")
* @Seguro(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modelo()
*/
público função registrar agora(Pedir $pedir)
{
$params = $request->request->all()[“nome_do_meu_formulário”];
$formulário = $ This->criarFormulário(novo UserType(UserType::REGISTER), novo Do utilizador());
$formulário->enviar($pedido);
if (array_key_exists(“senha_simples”, $params) && array_key_exists(“simples_senha2”, $params) && $params[“senha_simples”] == $params[“simples_senha2”]) {
if ($form->isValid()) {
$dados = $form->getData();
$data->setPassword($ This->container->get(“security.encoder_factory”)->getEncoder($data)->encodePassword($params[“senha_simples”], $data->getSalt()));
$em->persist($data);
$em->flush();
retorno $ This->redirecionar($ This->generateUrl("Conecte-se", ordem(" mensagem " => “Você recebeu um e-mail para validar sua conta. »)));
}
}
retorno ordem(
“erros” => $parametros[“senha_simples”] == $params[“simples_senha2”]? $form->getErrors(): ordem(“As duas senhas devem ser iguais”),
"forma" => $form->createView(),
);
}
|
Aqui vamos detalhar rapidamente o de gestão de documentos para registrar um novo usuário.
- Nós olhamos se todos os campos obrigatórios forem inseridos corretamente, incluindo os dois campos "senha", e se os dois últimos forem idênticos.
- Nós codificamos a senha e nós o “configuramos” na entidade.
- Em caso de erro, devolvemos o formulário com o erro que julgamos dever ser detalhado.
Crie um recurso para redefinir sua senha
Agora seu usuário pode fazer login, mas o que faremos se ele perder sua senha. É óbvio que não vamos configurar um endereço de e-mail de contato dedicado às suas operações inúteis.
Como você viu acima, costumo declarar dois métodos para cada uma das minhas funcionalidades: um dos meus métodos é responsável por gerenciar a visão criada após uma solicitação ENTRE e resultado de um pedido POST. Você pode absolutamente concatenar esses dois métodos em um único e mesmo método.
1
2
3
4
5
6
7
8
9
|
/ **
* @Método({"PEGAR"})
* @Rota(“/reset”, nome=”reset”)
* @Seguro(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modelo()
*/
público função redefinir() {
retorno ordem();
}
|
Em uma segunda etapa, declararemos o método complementar gerenciando as solicitações POST.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/ **
* @Método({"PUBLICAR"})
* @Rota("/reiniciar")
* @Seguro(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
público função reiniciar agora(Pedir $pedir)
{
$params = $request->request->all();
if (!array_key_exists("Conecte-se", $params)) {
jogar novo Exceção(“Nenhum login fornecido”);
}
$login = &$params["Conecte-se"];
$em = $ This->container->get(“doctrine.orm.default_entity_manager”);
$user = $em->getRepository(“NamespaceMyBundle:Usuário”)->encontrarOneBy(ordem("Conecte-se" => $login));
if ($usuário == nulo) {
retorno $ This->redirecionar($ This->generateUrl("Conecte-se", ordem()));
}
$senha = “minhaSenhaRandow”;
$user->setPassword($ This->container->get(“security.encoder_factory”)->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($usuário);
$em->flush();
// Enviamos a senha por e-mail
retorno $ This->redirecionar($ This->generateUrl("Conecte-se", ordem()));
}
|
Este método foi projetado para resetter a senha de um usuário que forneceu seu Nome de usuário de login. No meu caso, a senha foi enviada por e-mail. Vou deixar você adicionar essa linha galante.
- Então vamos pesquisar usuário.
- Geramos uma senha que viemos informar no usuário uma vez que ele tenha codificado de acordo com as regras que você definiu.
Configurar alteração de senha
Neste ponto, nosso usuário pode gerar uma nova senha caso tenha perdido, mas caso queira apenas trocá-la, precisamos de uma porta para definir uma porta.
1
2
3
4
5
6
7
8
9
|
/ **
* @Método({"PEGAR"})
* @Rota(“/change”, nome=”change-password”)
* @Seguro(roles=”IS_AUTHENTICATED_FULLY”)
* @Modelo()
*/
público função alterar() {
retorno ordem();
}
|
Aqui está o código para gerar a exibição. Primeiro, você terá que digitar sua senha antiga e, em seguida, digite sua nova senha duas vezes. A segunda vez sendo a confirmação.
Agora vamos ver o código para reinicializador a senha. O processo é semelhante a gerar uma nova senha aleatória.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
/ **
* @Método({"PUBLICAR"})
* @Rota("/mudar")
* @Seguro(roles=”IS_AUTHENTICATED_FULLY”)
* @Modelo()
*/
público função mude agora(Pedir $pedir)
{
$params = $request->request->all();
if (!array_key_exists("atual", $parametros)
|| !array_key_exists("novo", $parametros)
|| !array_key_exists(“novo2”, $params))
{
retorno ordem("Erro" => "Por favor preencha todos os campos");
}
$em = $ This->container->get(“doctrine.orm.default_entity_manager”);
$usuário= $ This->getUser();
$user_encoders = $ This->container->get(“security.encoder_factory”)->getEncoder($usuário);
$user_repository = $em->getRepository(“NamespaceMyBundle:Usuário”);
$current_password_encoded = $user_encoders->encodePassword($params["atual"], $usuário->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["novo"], $usuário->getSalt());
if ($user_repository->findOneBy(ordem("senha" => $current_password_encoded)) == nulo) {
retorno ordem("Erro" => “A senha atual está errada”);
} elseif ($parametros["novo"] != $params[“novo2”]) {
retorno ordem("Erro" => "A senha dos dois campos não é a mesma");
}
$user->setPassword($new_password_encoded);
$em->persist($usuário);
$em->flush();
retorno $ This->redirecionar($ This->generateUrl("sair", ordem()));
}
|
Se você demorar 1 minuto para ler o código, verá que este é particularmente simples.
- Primeiramente, verificamos se os três campos (senha antiga, nova senha e confirmação) foram preenchidos corretamente.
- On Digite a senha atual e nós a comparamos com a senha atualmento no banco de dados para ver se corresponde à senha antiga digitada.
- Verificamos se as "duas" novas senhas são idênticas.
- Digite a nova senha e empurrar na entidade.
Ativação da conta dele
Este recurso não é detalhado perfeitamente em outros snippets acima. Sua finalidade é desbloquear um usuário que acabou de se registrar, quando tiver validado seu e-mail, por exemplo. Essa funcionalidade é desenvolvida em quase todas as plataformas que conhecemos por vários motivos. Para configurar o bloqueio de um usuário, você também pode precisar implementar um provedor.
- bloco/limitar contas falsificação e o Spam.
- Vérifier que o usuário preencheu um endereço de e-mail que parece utilizável à primeira vista.
- Excluir contas que não foram validadas após um determinado período de tempo.
Fluxo de trabalho
- Um usuário se cadastra. A conta dele é bloqueada por meio de um campo específico para você. Este campo deve impedi-lo de se conectar, desde que este campo indique que a conta está desativada.
1
2
3
4
5
6
7
8
|
// NamespaceMyBundleEntityUser
classe Utilizador {
público função __construir() {
$ This->token = hash("sha512", uniqid());
}
...
}
|
1
|
$user->setEnabled(falso);
|
- O usuário recebeu um e-mail quando seu perfil foi rubor no banco de dados. Este e-mail deve fazer parte de um endereço gerado por você.
Nesta estrada, um token ou identificador único deve ser dado permitindo que o usuário em questão seja encontrado. Aconselho você a usar um UUID4 que se destina a ser aleatório. Você pode encontrar a lista de UUIDs, bem como a descrição de todas as versões.
1
2
3
4
|
/ **
* @Rota(“/ativar”, nome =”ativar”)
*/
público função ativado() {...}
|
1
|
$ This->generateUrl("ativar", ordem(« token » => $usuário->obterToken()), verdadeiro);
|
Você deve ter um URL como este.
1
|
http://nome do host/ativar?token=meuÚnicoToken
|
- O usuário abre seu e-mail e tenta ativar sua conta clicando no link fornecido. Entramos então no processo abaixo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/ **
* @Método({"PEGAR"})
* @Rota(“/ativar”, nome =”ativar”)
* @Seguro(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modelo()
*/
público função ativado(Pedir $pedir) {
$parametros = ordem();
$token = $pedido->consulta->obter(« token »);
$em = $ This->container->get(“doctrine.orm.default_entity_manager”);
$user = $em->getRepository(“NamespaceMyBundle:Usuário”)->encontrarOneBy(ordem(« token » => $token));
if ($usuário != nulo) {
$user->setEnabled(verdadeiro);
$em->persist($usuário);
$em->flush();
$parametros["ativar"] = verdadeiro;
} outro {
$parametros["ativar"] = falso;
}
retorno $params;
}
|
Com esse processo, você não deve ter problemas para ativar a validação da conta do usuário.
Você pode encontrar este código equivalente neste Gist.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
usar JMSSecurityExtraBundleAnotaçãoConfie;
usar SensioPacoteFrameworkExtraBundleConfiguraçãoMétodo;
usar SensioPacoteFrameworkExtraBundleConfiguraçãoRota;
usar SensioPacoteFrameworkExtraBundleConfiguraçãoModelo;
usar SymfonyPacotePacote de estruturacontroladorcontrolador;
usar SymfonyComponenteHttpFoundationSOLICITE;
usar SymfonyComponenteSegurançanúcleoContexto de Segurança;
classe SecurityController se estende controlador
{
/ **
* @Método({"PEGAR"})
* @Rota(“/login”, nome=”login”)
* @Modelo()
*/
público função entrar(Pedir $pedir)
{
$pedido = $ This->getRequest();
$sessão = $request->getSession();
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$erro = $request->atributos->get(SecurityContext::AUTHENTICATION_ERROR);
} outro {
$erro = $sessão->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
$parametros = ordem(
“último_nome de usuário” => $session->get(SecurityContext::LAST_USERNAME),
"Erro" => $erro,
" mensagem " => $request->get(" mensagem "),
);
if ($request->isXmlHttpRequest()) {
retorno $ This->render(“GCDirectoryMainBundle:Security:login-ajax.html.twig”, $parametros);
}
retorno $params;
}
/ **
* @Método({"PUBLICAR"})
* @Rota(“/login_check”, nome=”login_check”)
*/
público função verificar()
{
jogar novo Exceção de tempo de execução('Você deve configurar o caminho de verificação para ser manipulado pelo firewall usando form_login na configuração do seu firewall de segurança.');
}
/ **
* @Método({"PEGAR"})
* @Rota(“/logout”, nome=”logout”)
*/
público função Sair()
{
jogar novo Exceção de tempo de execução('Você deve ativar o logout na configuração do seu firewall de segurança.');
}
/ **
* @Método({"PEGAR"})
* @Rota(“/reset”, nome=”reset”)
* @Seguro(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modelo()
*/
público função redefinir() {
retorno ordem();
}
/ **
* @Método({"PUBLICAR"})
* @Rota("/reiniciar")
* @Seguro(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
público função reiniciar agora(Pedir $pedir)
{
$params = $request->request->all();
if (!array_key_exists("Conecte-se", $params)) {
jogar novo Exceção(“Nenhum login fornecido”);
}
$login = &$params["Conecte-se"];
$em = $ This->container->get(“doctrine.orm.default_entity_manager”);
$user = $em->getRepository(“NamespaceMyBundle:Usuário”)->encontrarOneBy(ordem("Conecte-se" => $login));
if ($usuário == nulo) {
retorno $ This->redirecionar($ This->generateUrl("Conecte-se", ordem()));
}
$senha = “minhaSenhaRandow”;
$user->setPassword($ This->container->get(“security.encoder_factory”)->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($usuário);
$em->flush();
retorno $ This->redirecionar($ This->generateUrl("Conecte-se", ordem()));
}
/ **
* @Método({"PEGAR"})
* @Rota(“/change”, nome=”change-password”)
* @Seguro(roles=”IS_AUTHENTICATED_FULLY”)
* @Modelo()
*/
público função alterar() {
retorno ordem();
}
/ **
* @Método({"PUBLICAR"})
* @Rota("/mudar")
* @Seguro(roles=”IS_AUTHENTICATED_FULLY”)
* @Modelo()
*/
público função mude agora(Pedir $pedir)
{
$params = $request->request->all();
if (!array_key_exists("atual", $parametros)
|| !array_key_exists("novo", $parametros)
|| !array_key_exists(“novo2”, $params))
{
retorno ordem("Erro" => "Por favor preencha todos os campos");
}
$em = $ This->container->get(“doctrine.orm.default_entity_manager”);
$usuário= $ This->getUser();
$user_encoders = $ This->container->get(“security.encoder_factory”)->getEncoder($usuário);
$user_repository = $em->getRepository(“NamespaceMyBundle:Usuário”);
$current_password_encoded = $user_encoders->encodePassword($params["atual"], $usuário->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["novo"], $usuário->getSalt());
if ($user_repository->findOneBy(ordem("senha" => $current_password_encoded)) == nulo) {
retorno ordem("Erro" => “A senha atual está errada”);
} elseif ($parametros["novo"] != $params[“novo2”]) {
retorno ordem("Erro" => "A senha dos dois campos não é a mesma");
}
$user->setPassword($new_password_encoded);
$em->persist($usuário);
$em->flush();
retorno $ This->redirecionar($ This->generateUrl("sair", ordem()));
}
/ **
* @Método({"PEGAR"})
* @Rota(“/registro”, nome=”registro”)
* @Seguro(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modelo()
*/
público função cadastre-se()
{
$formulário = $ This->criarFormulário(novo UserType(UserType::REGISTER), novo Do utilizador());
retorno ordem(
"forma" => $form->createView(),
);
}
/ **
* @Método({"PUBLICAR"})
* @Rota("/registro")
* @Seguro(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modelo()
*/
público função registrar agora(Pedir $pedir)
{
$params = $request->request->all()[“nome_do_meu_formulário”];
$formulário = $ This->criarFormulário(novo UserType(UserType::REGISTER), novo Do utilizador());
$formulário->enviar($pedido);
if (array_key_exists(“senha_simples”, $params) && array_key_exists(“simples_senha2”, $params) && $params[“senha_simples”] == $params[“simples_senha2”]) {
if ($form->isValid()) {
$dados = $form->getData();
$data->setPassword($ This->container->get(“security.encoder_factory”)->getEncoder($data)->encodePassword($params[“senha_simples”], $data->getSalt()));
$em->persist($data);
$em->flush();
retorno $ This->redirecionar($ This->generateUrl("Conecte-se", ordem(" mensagem " => “Você recebeu um e-mail para validar sua conta. »)));
}
}
retorno ordem(
“erros” => $parametros[“senha_simples”] == $params[“simples_senha2”]? $form->getErrors(): ordem(“As duas senhas devem ser iguais”),
"forma" => $form->createView(),
);
}
/ **
* @Método({"PEGAR"})
* @Rota(“/ativar”, nome =”ativar”)
* @Seguro(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modelo()
*/
público função ativado(Pedir $pedir) {
$parametros = ordem();
$token = $pedido->consulta->obter(« token »);
$em = $ This->container->get(“doctrine.orm.default_entity_manager”);
$user = $em->getRepository(“NamespaceMyBundle:Usuário”)->encontrarOneBy(ordem(« token » => $token));
if ($usuário != nulo) {
$user->setActive(User::ACTIVE_ACTIVE);
$em->persist($usuário);
$em->flush();
$parametros["ativar"] = verdadeiro;
} outro {
$parametros["ativar"] = falso;
}
retorno $params;
}
}
|