Implementa il tuo SecurityController
Agenzia web » Notizie digitali » Implementa il tuo SecurityController

Implementa il tuo SecurityController

Di recente ho scritto un articolo per la mia azienda sulla gestione degli utenti e della loro autenticazione in modo nativo utilizzando Symfony2 Core, e quindi senza FOSUserBundle. A seguito di questo già ricco primo articolo, ho voluto descrivere una seconda parte altrettanto utile che ci permetterà di impostare rapidamente le funzioni essenziali, ovvero reimpostare la password, modificare la password, convalidare il proprio account o addirittura registrarsi. Azioni altrettanto essenziali quando si dispone di un sistema che gestisce gli utenti.

Configurare un SecurityController

Innanzitutto, se non hai seguito il primo tutorial su come impostare la gestione degli utenti, ti consiglio di dare un'occhiata. Se hai seguito la soluzione, dovresti logicamente avere un SecurityController o qualcos'altro. Nel mio caso, ho solo tre metodi, solo uno dei quali è realmente utilizzabile.

  1. loginAzione
    Questo metodo connette un utente.
  2. checkAzione
    Questo metodo consente semplicemente di dichiarare un percorso per il firewall, consentendo a un utente di connettersi sul lato server.
  3. logoutAzione
    Questo metodo viene utilizzato per dichiarare un percorso per il firewall che consente la disconnessione di un utente.

Apri la nostra piattaforma a nuovi utenti

Sarebbe particolarmente interessante se i nostri utenti potessero connettersi, e quindi potersi registrare in anticipo.

Innanzitutto, generiamo il modulo con le informazioni che vuoi chiedere al tuo utente.

Per quanto riguarda il modulo che utilizzerai per registrare il tuo utente, sappi che il campo " parola d'ordine non dovrebbe essere nella tua forma. Tuttavia, dovrai aggiungere due campi " non mappato per avere la password desiderata inserita due volte.

1
2
3
4
5
6
7
8
9
10
11
12
13
/ **
 * @Metodo({"OTTENERE"})
 * @Strada(“/registrati”, nome=”registrati”)
 * @Sicuro(ruoli=”IS_AUTHENTICATED_ANONYMOUSLY”)
 * @Modello()
 */
la percezione function registro()
{
    $forma = $ This->createForm(nuovi TipoUtente(TipoUtente::REGISTRAZIONE), nuovi Utente());
    ritorno schieramento(
        "modulo" => $form->createView(),
        );
}

Quindi, è quando il tuo utente torna con il suo modulo compilato che dovremo registrarlo o rifiutare il suo file :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
/ **
* @Metodo({"INVIARE"})
* @Strada("/Registrati")
* @Sicuro(ruoli=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modello()
*/
la percezione function Iscriviti ora(Richiesta $richiesta)
{
$params = $request->request->all()[“nome_del_mio_modulo”];
$forma = $ This->createForm(nuovi TipoUtente(TipoUtente::REGISTRAZIONE), nuovi Utente());
$modulo->invia($richiesta);
if (array_key_exists("password_semplice", $params) && array_key_exists("semplice_password2", $param) && $param["password_semplice"] == $param["semplice_password2"]) {
if ($form->isValid()) {
$dati = $form->getData();
$dati->setPassword($ This->contenitore->prendi("security.encoder_factory")->getEncoder($data)->encodePassword($params["password_semplice"], $dati->getSalt()));
$em->persisti($dati);
$em->flush();
ritorno $ This->reindirizzare($ This->generaUrl("login", schieramento(" Messaggio " => “Hai ricevuto un'e-mail per convalidare il tuo account. »)));
}
}
ritorno schieramento(
"errori" => $param["password_semplice"] == $param["semplice_password2"]? $form->getErrors(): schieramento(“Le due password devono essere uguali”),
"modulo" => $form->createView(),
);
}

Qui descriveremo rapidamente in dettaglio il flusso di lavoro per registrare un nuovo utente.

  1. Noi guardiamo se tutti i campi obbligatori sono inseriti correttamente, compresi i due campi "password", e se gli ultimi due sono identici.
  2. Codifichiamo la password e lo "impostiamo" nell'entità.
  3. In caso di errore, restituiamo il modulo con l'errore che riteniamo debba essere dettagliato.

Crea una funzione per reimpostare la tua password

Ora il tuo utente può accedere ma cosa faremo se perde la sua password. È ovvio che non creeremo un indirizzo email di contatto dedicato alle sue operazioni inutili.

Come hai visto sopra, di solito dichiaro due metodi per ciascuna delle mie funzionalità: uno dei miei metodi è responsabile della gestione della vista creata a seguito di una richiesta GET e il risultato di una richiesta POST. Puoi assolutamente concatenare questi due metodi in uno e lo stesso metodo.

1
2
3
4
5
6
7
8
9
/ **
  * @Metodo({"OTTENERE"})
  * @Strada(“/reset”, nome=”reset”)
  * @Sicuro(ruoli=”IS_AUTHENTICATED_ANONYMOUSLY”)
  * @Modello()
  */
  la percezione function azzerare() {
   ritorno schieramento();
  }

In una seconda fase, dichiareremo il metodo complementare che gestisce le richieste 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
/ **
* @Metodo({"INVIARE"})
* @Strada("/Ripristina")
* @Sicuro(ruoli=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
la percezione function reimposta ora(Richiesta $richiesta)
{
$params = $request->request->all();
if (!array_key_exists("login", $parametri)) {
gettare nuovi Eccezione("Nessun accesso fornito");
}
$login = &$parametri["login"];
$ em = $ This->contenitore->prendi(“doctrine.orm.default_entity_manager”);
$utente = $em->getRepository(“NamespaceMyBundle:Utente”)->trovaUnoPer(schieramento("login" => $accesso));
if ($utente == nullo) {
ritorno $ This->reindirizzare($ This->generaUrl("login", schieramento()));
}
$password = "la miapasswordcasuale";
$utente->impostapassword($ This->contenitore->prendi("security.encoder_factory")->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persiste($utente);
$em->flush();
// Inviamo la password via e-mail
ritorno $ This->reindirizzare($ This->generaUrl("login", schieramento()));
}

Questo metodo è stato progettato per resetter la password di un utente che ha fornito la sua login/nome utente. Nel mio caso, la password è stata poi inviata via e-mail. Ti lascerò aggiungere quella battuta galante.

  1. Quindi stiamo andando cerca utente.
  2. Generiamo una password che veniamo ad informare nell'utente una volta che ha codificato secondo le regole che hai definito.

Impostare la modifica della password

A questo punto, il nostro utente può generare una nuova password se l'ha persa, ma nel caso volesse solo cambiarla, abbiamo bisogno di una porta per definire una porta.

1
2
3
4
5
6
7
8
9
/ **
* @Metodo({"OTTENERE"})
* @Strada(“/cambia”, nome=”cambia-password”)
* @Sicuro(ruoli=”IS_AUTHENTICATED_FULLY”)
* @Modello()
*/
la percezione function il cambiamento() {
ritorno schieramento();
}

Ecco il codice per generare la vista. Innanzitutto, dovrai inserire la tua vecchia password, quindi inserire la nuova password due volte. La seconda volta è la conferma.

Ora vedremo il codice per resetter la password. IL processi è simile alla generazione di una nuova password casuale.

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
/ **
 * @Metodo({"INVIARE"})
 * @Strada("/modifica")
 * @Sicuro(ruoli=”IS_AUTHENTICATED_FULLY”)
 * @Modello()
 */
la percezione function cambia ora(Richiesta $richiesta)
{
    $params = $request->request->all();
    if (!array_key_exists("attuale", $parametri)
        || !array_key_esiste("nuovo", $parametri)
        || !array_key_esiste("nuovo2", $parametri))
    {
        ritorno schieramento("Errore" => "Per favore compila tutti i campi");
    }
    $ em = $ This->contenitore->prendi(“doctrine.orm.default_entity_manager”);
    $utente = $ This->getUser();
    $user_encoders = $ This->contenitore->prendi("security.encoder_factory")->getEncoder($utente);
    $user_repository = $em->getRepository(“NamespaceMyBundle:Utente”);
    $current_password_encoded = $user_encoders->encodePassword($params["attuale"], $utente->getSalt());
    $new_password_encoded = $user_encoders->encodePassword($params["nuovo"], $utente->getSalt());
    if ($user_repository->findOneBy(schieramento("parola d'ordine" => $current_password_encoded)) == nullo) {
        ritorno schieramento("Errore" => "La password attuale è errata");
    } elseif ($parami["nuovo"] != $param["nuovo2"]) {
        ritorno schieramento("Errore" => "La password dei due campi non è la stessa");
    }
    $utente->impostaPassword($nuova_password_codificata);
    $em->persiste($utente);
    $em->flush();
    ritorno $ This->reindirizzare($ This->generaUrl("disconnettersi", schieramento()));
}

Se impieghi 1 minuto per leggere il codice, vedrai che questo è particolarmente semplice.

  1. Per prima cosa controlliamo se i tre campi (vecchia password, nuova password e conferma) sono stati inseriti correttamente.
  2. On inserire la parola d'ordine attuale e lo confrontiamo con la password correntemento nel database per vedere se corrisponde alla vecchia password inserita.
  3. Controlliamo se le "due" nuove password lo sono identiques.
  4. Inserisci la nuova password e spingere nell'ente.

Attivazione del suo account

Questa caratteristica non è dettagliata perfettamente in altri frammenti Sopra. Il suo scopo è sbloccare un utente che si è appena registrato, ad esempio quando ha convalidato la sua e-mail. Questa funzionalità è sviluppata su quasi tutte le piattaforme che conosciamo per diversi motivi. Per configurare il blocco di un utente, potrebbe anche essere necessario implementare un provider.

  • blocco/limitare gli account falso e carne in scatola.
  • Verifier che l'utente ha inserito un indirizzo e-mail che a prima vista appare utilizzabile.
  • Rimuovere account che non sono stati convalidati dopo un certo periodo di tempo.

Workflow

  1. Un utente si registra. Il suo account viene quindi bloccato tramite un campo specifico per te. Questo campo dovrebbe quindi impedirgli di connettersi fintanto che questo campo indica che l'account è disabilitato.
1
2
3
4
5
6
7
8
// Spazio dei nomiMyBundleEntityUser
classe Utente {
la percezione function __costruire() {
$ This->token = cancelletto(“sha512”, uniqid());
}
...
}
1
$utente->setEnabled(falso);
  1. L'utente ha ricevuto un'e-mail quando il suo profilo era sciacquone nella banca dati. Questa email deve far parte di un indirizzo che hai generato.
    In questa strada, a token o deve essere fornito un identificatore univoco che consenta di trovare l'utente interessato. Ti consiglio di utilizzare un UUID4 che dovrebbe essere casuale. Puoi trovare l'elenco degli UUID e la descrizione di tutte le versioni.
1
2
3
4
/ **
* @Strada(“/activate”, nome=”activate”)
*/
la percezione function attivare() {...}
1
$ This->generaUrl("attivare", schieramento(« token » => $utente->ottieniToken()), vero);

Dovresti avere un URL come questo.

1
http://hostname/activate?token=mioUnicoToken
  1. L'utente apre la sua e-mail e tenta di attivare il suo account facendo clic sul collegamento fornito. Quindi entriamo nel processo di seguito.
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
/ **
 * @Metodo({"OTTENERE"})
 * @Strada(“/activate”, nome=”activate”)
 * @Sicuro(ruoli=”IS_AUTHENTICATED_ANONYMOUSLY”)
 * @Modello()
 */
la percezione function attivare(Richiesta $richiesta) {
    $param = schieramento();
    $token = $richiesta->query->get(« token »);
    $ em = $ This->contenitore->prendi(“doctrine.orm.default_entity_manager”);
$utente = $em->getRepository(“NamespaceMyBundle:Utente”)->trovaUnoPer(schieramento(« token » => $token));
    if ($utente!= nullo) {
        $utente->setEnabled(vero);
        $em->persiste($utente);
        $em->flush();
        $param["attivare"🇧🇷 vero;
    } altro {
        $param["attivare"🇧🇷 falso;
    }
    ritorno $param;
}

Con questo processo non dovresti avere problemi ad abilitare la convalida dell'account utente.

Puoi trovare questo codice equivalente su questo 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
uso JMSSecurityExtraBundleAnnotazioneSicuro;
uso SensiimpacchettareFrameworkExtraBundleConfigurazionemetodo;
uso SensiimpacchettareFrameworkExtraBundleConfigurazionestrada;
uso SensiimpacchettareFrameworkExtraBundleConfigurazioneModello;
uso symfonyimpacchettareFrameworkBundleControllerController;
uso symfonyComponenteHttp FoundationRichiesta;
uso symfonyComponenteSicurezzaNucleoContesto di sicurezza;
classe SecurityController si estende Controller
{
/ **
* @Metodo({"OTTENERE"})
* @Strada(“/login”, nome=”login”)
* @Modello()
*/
la percezione function accesso(Richiesta $richiesta)
{
$richiesta= $ This->getRichiesta();
$sessione = $richiesta->getSession();
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} altro {
$errore = $sessione->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
$param = schieramento(
“cognome_utente” => $session->get(SecurityContext::LAST_USERNAME),
"Errore" => $errore,
" Messaggio " => $richiesta->ottieni(" Messaggio "),
);
if ($request->isXmlHttpRequest()) {
ritorno $ This->render("GCDirectoryMainBundle:Sicurezza:login-ajax.html.twig", $parametri);
}
ritorno $param;
}
/ **
* @Metodo({"INVIARE"})
* @Strada(“/login_check”, nome=”login_check”)
*/
la percezione function dai un'occhiata()
{
gettare nuovi RuntimeException ('È necessario configurare il percorso di controllo in modo che venga gestito dal firewall utilizzando form_login nella configurazione del firewall di sicurezza.');
}
/ **
* @Metodo({"OTTENERE"})
* @Strada(“/logout”, name=”logout”)
*/
la percezione function il logout()
{
gettare nuovi RuntimeException ('Devi attivare il logout nella configurazione del tuo firewall di sicurezza.');
}
/ **
* @Metodo({"OTTENERE"})
* @Strada(“/reset”, nome=”reset”)
* @Sicuro(ruoli=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modello()
*/
la percezione function azzerare() {
ritorno schieramento();
}
/ **
* @Metodo({"INVIARE"})
* @Strada("/Ripristina")
* @Sicuro(ruoli=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
la percezione function reimposta ora(Richiesta $richiesta)
{
$params = $request->request->all();
if (!array_key_exists("login", $parametri)) {
gettare nuovi Eccezione("Nessun accesso fornito");
}
$login = &$parametri["login"];
$ em = $ This->contenitore->prendi(“doctrine.orm.default_entity_manager”);
$utente = $em->getRepository(“NamespaceMyBundle:Utente”)->trovaUnoPer(schieramento("login" => $accesso));
if ($utente == nullo) {
ritorno $ This->reindirizzare($ This->generaUrl("login", schieramento()));
}
$password = "la miapasswordcasuale";
$utente->impostapassword($ This->contenitore->prendi("security.encoder_factory")->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persiste($utente);
$em->flush();
ritorno $ This->reindirizzare($ This->generaUrl("login", schieramento()));
}
/ **
* @Metodo({"OTTENERE"})
* @Strada(“/cambia”, nome=”cambia-password”)
* @Sicuro(ruoli=”IS_AUTHENTICATED_FULLY”)
* @Modello()
*/
la percezione function il cambiamento() {
ritorno schieramento();
}
/ **
* @Metodo({"INVIARE"})
* @Strada("/modifica")
* @Sicuro(ruoli=”IS_AUTHENTICATED_FULLY”)
* @Modello()
*/
la percezione function cambia ora(Richiesta $richiesta)
{
$params = $request->request->all();
if (!array_key_exists("attuale", $parametri)
|| !array_key_esiste("nuovo", $parametri)
|| !array_key_esiste("nuovo2", $parametri))
{
ritorno schieramento("Errore" => "Per favore compila tutti i campi");
}
$ em = $ This->contenitore->prendi(“doctrine.orm.default_entity_manager”);
$utente = $ This->getUser();
$user_encoders = $ This->contenitore->prendi("security.encoder_factory")->getEncoder($utente);
$user_repository = $em->getRepository(“NamespaceMyBundle:Utente”);
$current_password_encoded = $user_encoders->encodePassword($params["attuale"], $utente->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["nuovo"], $utente->getSalt());
if ($user_repository->findOneBy(schieramento("parola d'ordine" => $current_password_encoded)) == nullo) {
ritorno schieramento("Errore" => "La password attuale è errata");
} elseif ($parami["nuovo"] != $param["nuovo2"]) {
ritorno schieramento("Errore" => "La password dei due campi non è la stessa");
}
$utente->impostaPassword($nuova_password_codificata);
$em->persiste($utente);
$em->flush();
ritorno $ This->reindirizzare($ This->generaUrl("disconnettersi", schieramento()));
}
/ **
* @Metodo({"OTTENERE"})
* @Strada(“/registrati”, nome=”registrati”)
* @Sicuro(ruoli=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modello()
*/
la percezione function registro()
{
$forma = $ This->createForm(nuovi TipoUtente(TipoUtente::REGISTRAZIONE), nuovi Utente());
ritorno schieramento(
"modulo" => $form->createView(),
);
}
/ **
* @Metodo({"INVIARE"})
* @Strada("/Registrati")
* @Sicuro(ruoli=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modello()
*/
la percezione function Iscriviti ora(Richiesta $richiesta)
{
$params = $request->request->all()[“nome_del_mio_modulo”];
$forma = $ This->createForm(nuovi TipoUtente(TipoUtente::REGISTRAZIONE), nuovi Utente());
$modulo->invia($richiesta);
if (array_key_exists("password_semplice", $params) && array_key_exists("semplice_password2", $param) && $param["password_semplice"] == $param["semplice_password2"]) {
if ($form->isValid()) {
$dati = $form->getData();
$dati->setPassword($ This->contenitore->prendi("security.encoder_factory")->getEncoder($data)->encodePassword($params["password_semplice"], $dati->getSalt()));
$em->persisti($dati);
$em->flush();
ritorno $ This->reindirizzare($ This->generaUrl("login", schieramento(" Messaggio " => “Hai ricevuto un'e-mail per convalidare il tuo account. »)));
}
}
ritorno schieramento(
"errori" => $param["password_semplice"] == $param["semplice_password2"]? $form->getErrors(): schieramento(“Le due password devono essere uguali”),
"modulo" => $form->createView(),
);
}
/ **
* @Metodo({"OTTENERE"})
* @Strada(“/activate”, nome=”activate”)
* @Sicuro(ruoli=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Modello()
*/
la percezione function attivare(Richiesta $richiesta) {
$param = schieramento();
$token = $richiesta->query->get(« token »);
$ em = $ This->contenitore->prendi(“doctrine.orm.default_entity_manager”);
$utente = $em->getRepository(“NamespaceMyBundle:Utente”)->trovaUnoPer(schieramento(« token » => $token));
if ($utente!= nullo) {
$user->setActive(Utente::ACTIVE_ACTIVE);
$em->persiste($utente);
$em->flush();
$param["attivare"🇧🇷 vero;
} altro {
$param["attivare"🇧🇷 falso;
}
ritorno $param;
}
}

★ ★ ★ ★ ★