Implementați-vă propriul SecurityController
Am scris recent un articol pentru compania mea despre gestionarea utilizatorilor și autentificarea lor nativ folosind Symfony2 Core și, prin urmare, fără FOSUserBundle. În urma acestui prim articol deja bogat, am vrut să descriu o a doua parte la fel de utilă care ne va permite să setăm rapid funcțiile esențiale, și anume, resetarea parolei, schimbarea parolei, validarea contului sau chiar înregistrarea. Acțiuni la fel de esențiale atunci când aveți un sistem care gestionează utilizatori.
Configurați un SecurityController
În primul rând, dacă nu ați urmat primul tutorial despre cum să configurați gestionarea utilizatorilor, vă sfătuiesc să aruncați o privire. Dacă ați urmat soluția, ar trebui logic să aveți un SecurityController sau altceva. În cazul meu, am doar trei metode, dintre care doar una este cu adevărat utilizabilă.
- loginAction
Această metodă conectează un utilizator. - verificaAcțiune
Această metodă vă permite pur și simplu să declarați o rută pentru firewall, permițând unui utilizator să se conecteze pe partea serverului. - logoutAction
Această metodă este folosită pentru a declara o rută pentru firewall-ul permițând unui utilizator să fie deconectat.
Deschide platforma noastră pentru noi utilizatori
Ar fi deosebit de interesant dacă utilizatorii noștri s-ar putea conecta și, prin urmare, să se poată înregistra în prealabil.
În primul rând, generăm formularul cu informațiile pe care doriți să le solicitați utilizatorului dvs.
În ceea ce privește formularul pe care îl veți utiliza pentru a vă înregistra utilizatorul, știi că câmpul" parola nu ar trebui să fie în forma ta. Cu toate acestea, va trebui să adăugați două câmpuri " necartografiate pentru a avea parola dorită introdusă de două ori.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/ **
* @Metodă({"OBȚINE"})
* @Drum(“/înregistrare”, nume=”înregistrare”)
* @Sigur(roluri=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Șablon()
*/
public funcţie Inregistreaza-te()
{
$form = $ asta->createForm(nou UserType(UserType::REGISTER), nou Utilizator());
reveni mulțime(
"formă" => $form->createView(),
);
}
|
Apoi, atunci când utilizatorul tău revine cu formularul completat, va trebui să-l înregistrăm sau să-i respingem fișierul :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
|
/ **
* @Metodă({"POST"})
* @Drum("/Inregistreaza-te")
* @Sigur(roluri=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Șablon()
*/
public funcţie înregistrează-te acum(Solicitare $request)
{
$params = $cerere->cerere->toate()[„numele_formularului_meu”];
$form = $ asta->createForm(nou UserType(UserType::REGISTER), nou Utilizator());
$form->submit($cerere);
if (array_key_exists(„parolă_pură”, $params) && array_key_exists(„parolă_clasă2”, $params) && $params[„parolă_pură”] == $params[„parolă_clasă2”]) {
if ($form->isValid()) {
$date = $form->getData();
$date->setPassword($ asta->container->get(„security.encoder_factory”)->getEncoder($date)->encodePassword($params[„parolă_pură”], $date->getSalt()));
$em->persist($date);
$em->flush();
reveni $ asta->redirecționare($ asta->generateUrl("log in", mulțime("mesaj" => „Ați primit un e-mail pentru a vă valida contul. »)));
}
}
reveni mulțime(
„erori” => $params[„parolă_pură”] == $params[„parolă_clasă2”]? $form->getErrors(): mulțime(„Cele două parole trebuie să fie aceleași”),
"formă" => $form->createView(),
);
}
|
Aici vom detalia rapid flux de lucru pentru a înregistra un utilizator nou.
- Ne uitam dacă toate câmpurile obligatorii sunt introduse corect, inclusiv cele două câmpuri „parolă” și dacă ultimele două sunt identice.
- Codăm parola și îl „setăm” în entitate.
- În cazul oricărei erori, returnăm formularul cu eroarea care credem că ar trebui detaliată.
Creați o funcție pentru a vă reseta parola
Acum utilizatorul tău se poate autentifica, dar ce vom face dacă își pierde parola. Este evident că nu vom configura o adresă de e-mail de contact dedicată operațiunilor sale inutile.
După cum ați văzut mai sus, declar de obicei două metode pentru fiecare dintre caracteristicile mele: una dintre metodele mele este responsabilă de gestionarea vizualizării create în urma unei solicitări GET și rezultatul unei cereri POST. Puteți concatena absolut aceste două metode într-una și aceeași metodă.
1
2
3
4
5
6
7
8
9
|
/ **
* @Metodă({"OBȚINE"})
* @Drum(“/resetare”, nume=”resetare”)
* @Sigur(roluri=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Șablon()
*/
public funcţie reseta() {
reveni mulțime,
}
|
Într-o a doua etapă, vom declara metoda complementară de gestionare a cererilor 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
|
/ **
* @Metodă({"POST"})
* @Drum(“/resetare”)
* @Sigur(roluri=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
public funcţie resetați acum(Solicitare $request)
{
$params = $cerere->cerere->toate();
if (!array_key_exists("log in", $params)) {
arunca nou Excepție(„Nu s-a dat login”);
}
$login = &$params["log in"];
$em = $ asta->container->get(„doctrine.orm.default_entity_manager”);
$user = $em->getRepository(„NamespaceMyBundle:Utilizator”)->findOneBy(mulțime("log in" => $login));
if ($utilizator == zero) {
reveni $ asta->redirecționare($ asta->generateUrl("log in", mulțime()));
}
$parolă = „myRandowPassword”;
$user->setPassword($ asta->container->get(„security.encoder_factory”)->getEncoder($user)->encodePassword($parola, $user->getSalt()));
$em->persist($utilizator);
$em->flush();
// Trimitem parola pe e-mail
reveni $ asta->redirecționare($ asta->generateUrl("log in", mulțime()));
}
|
Această metodă a fost concepută pentru resetare parola unui utilizator care a furnizat-o pe a lui autentificare/nume de utilizator. În cazul meu, parola a fost trimisă apoi prin e-mail. Te las să adaugi acea replică galanta.
- Deci mergem caută utilizatorul.
- Generăm o parolă că venim să informăm în utilizator odată ce acesta a codificat conform regulilor pe care le-ați definit.
Configurați schimbarea parolei
În acest moment, utilizatorul nostru poate genera o nouă parolă dacă aceasta a fost pierdută, dar în cazul în care dorește doar să o schimbe, avem nevoie de o poartă pentru a defini o poartă.
1
2
3
4
5
6
7
8
9
|
/ **
* @Metodă({"OBȚINE"})
* @Drum(“/schimbare”, nume=”schimbare-parola”)
* @Sigur(roluri=”IS_AUTHENTICATED_FULLY”)
* @Șablon()
*/
public funcţie Schimbare() {
reveni mulțime,
}
|
Iată codul pentru a genera vizualizarea. Mai întâi, va trebui să introduceți vechea parolă, apoi introduceți noua parolă de două ori. A doua oară fiind confirmarea.
Acum vom vedea codul pentru resetter parola. THE proces este similar cu generarea unei noi parole aleatorii.
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
|
/ **
* @Metodă({"POST"})
* @Drum("/Schimbare")
* @Sigur(roluri=”IS_AUTHENTICATED_FULLY”)
* @Șablon()
*/
public funcţie schimba acum(Solicitare $request)
{
$params = $cerere->cerere->toate();
if (!array_key_exists("actual", $params)
|| !array_key_exists("nou", $params)
|| !array_key_exists(„nou2”, $params))
{
reveni mulțime("eroare" => "Va rog completati toate campurile");
}
$em = $ asta->container->get(„doctrine.orm.default_entity_manager”);
$user= $ asta->getUser();
$user_encoders = $ asta->container->get(„security.encoder_factory”)->getEncoder($user);
$user_repository = $em->getRepository(„NamespaceMyBundle:Utilizator”);
$current_password_encoded = $user_encoders->encodePassword($params["actual"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["nou"], $user->getSalt());
if ($user_repository->findOneBy(mulțime("parola" => $parola_curente_codate)) == zero) {
reveni mulțime("eroare" => „Parola actuală este greșită”);
} elseif ($params["nou"] != $params[„nou2”]) {
reveni mulțime("eroare" => „Parola celor două câmpuri nu este aceeași”);
}
$user->setPassword($new_parola_encoded);
$em->persist($utilizator);
$em->flush();
reveni $ asta->redirecționare($ asta->generateUrl(„deconectare”, mulțime()));
}
|
Dacă ai nevoie de 1 minut pentru a citi codul, vei vedea că acesta este deosebit de simplu.
- În primul rând, verificăm dacă cele trei câmpuri (parolă veche, parolă nouă și confirmare) au fost introduse corect.
- On introduceți parola curent şi o comparăm cu parola curentăment în baza de date pentru a vedea dacă corespunde cu vechea parolă introdusă.
- Verificăm dacă cele „două” noi parole sunt identic.
- Introduceți noua parolă și împinge în entitate.
Activarea contului său
Această caracteristică nu este detaliată perfect în altele fragmente de cod de mai sus. Scopul acestuia este de a debloca un utilizator care tocmai s-a înregistrat, atunci când acesta și-a validat email-ul de exemplu. Această funcționalitate este dezvoltată pe aproape toate platformele pe care le cunoaștem din mai multe motive. Pentru a configura o blocare a unui utilizator, ar putea fi necesar să implementați și un furnizor.
- bloc/limita conturi fals și spam-.
- verifica că utilizatorul a completat o adresă de e-mail care pare utilizabilă la prima vedere.
- Elimina conturi care nu au fost validate după o anumită perioadă de timp.
Workflow
- Un utilizator se înregistrează. Contul lui este apoi blocat printr-un câmp specific pentru dvs. Acest câmp ar trebui să-l împiedice să se conecteze atâta timp cât acest câmp indică faptul că contul este dezactivat.
1
2
3
4
5
6
7
8
|
// NamespaceMyBundleEntityUser
clasă Utilizator {
public funcţie __construi() {
$ asta->token = hash(„sha512”, uniqid());
}
...
}
|
1
|
$user->setEnabled(fals);
|
- Utilizatorul a primit un e-mail când era profilul său culoare în baza de date. Acest e-mail trebuie să facă parte dintr-o adresă pe care o generați.
Pe acest drum, a token sau un identificator unic trebuie furnizat care să permită găsirea utilizatorului în cauză. Vă sfătuiesc să utilizați un UUID4 care este destinat să fie aleatoriu. Puteți găsi lista UUID-urilor, precum și descrierea tuturor versiunilor.
1
2
3
4
|
/ **
* @Drum(“/activare”, nume=”activare”)
*/
public funcţie activa() {...}
|
1
|
$ asta->generateUrl("Activati", mulțime(« token » => $user->getToken()), adevărat);
|
Ar trebui să aveți o adresă URL ca aceasta.
1
|
http://nume gazdă/activare?token=myUniqueToken
|
- Utilizatorul își deschide e-mailul și încearcă să își activeze contul făcând clic pe linkul furnizat. Apoi intrăm în procesul de mai jos.
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
|
/ **
* @Metodă({"OBȚINE"})
* @Drum(“/activare”, nume=”activare”)
* @Sigur(roluri=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Șablon()
*/
public funcţie activa(Solicitare $request) {
$params = mulțime,
$token = $cerere->interogare->get(« token »);
$em = $ asta->container->get(„doctrine.orm.default_entity_manager”);
$user = $em->getRepository(„NamespaceMyBundle:Utilizator”)->findOneBy(mulțime(« token » => $token));
if ($utilizator != zero) {
$user->setEnabled(adevărat);
$em->persist($utilizator);
$em->flush();
$params["Activati"] = adevărat;
} altfel {
$params["Activati"] = fals;
}
reveni $params;
}
|
Cu acest proces, nu ar trebui să aveți nicio problemă la activarea validării contului de utilizator.
Puteți găsi acest cod echivalent pe acest 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
|
utilizare JMSSecurityExtraBundleadnotareAsigura;
utilizare SensioPachetFrameworkExtraBundleConfiguraţieMetodă;
utilizare SensioPachetFrameworkExtraBundleConfiguraţieTraseul;
utilizare SensioPachetFrameworkExtraBundleConfiguraţieFormat;
utilizare SymfonyPachetFrameworkBundleoperator de date cu caracter personal, operator de date cu caracter personal, ;
utilizare SymfonyComponentFundația HttpCerere;
utilizare SymfonyComponentSecuritateNucleuSecurityContext;
clasă SecurityController extinde operator de date cu caracter personal,
{
/ **
* @Metodă({"OBȚINE"})
* @Drum(“/login”, nume=”login”)
* @Șablon()
*/
public funcţie Logare(Solicitare $request)
{
$cerere= $ asta->getRequest();
$session = $request->getSession();
if ($request->attributes->are(SecurityContext::AUTHENTICATION_ERROR)) {
$eroare = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} altfel {
$eroare = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
$params = mulțime(
„last_username” => $session->get(SecurityContext::LAST_USERNAME),
"eroare" => $eroare,
"mesaj" => $cerere->get("mesaj"),
);
if ($request->isXmlHttpRequest()) {
reveni $ asta->renda(„GCDirectoryMainBundle:Security:login-ajax.html.twig”, $params);
}
reveni $params;
}
/ **
* @Metodă({"POST"})
* @Drum(“/login_check”, nume=”login_check”)
*/
public funcţie verifica()
{
arunca nou RuntimeException(„Trebuie să configurați calea de verificare pentru a fi gestionată de firewall folosind form_login în configurația firewall-ului dumneavoastră de securitate.”);
}
/ **
* @Metodă({"OBȚINE"})
* @Drum(“/logout”, nume=”logout”)
*/
public funcţie Logout()
{
arunca nou RuntimeException(„Trebuie să activați deconectarea în configurația firewall-ului de securitate.”);
}
/ **
* @Metodă({"OBȚINE"})
* @Drum(“/resetare”, nume=”resetare”)
* @Sigur(roluri=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Șablon()
*/
public funcţie reseta() {
reveni mulțime,
}
/ **
* @Metodă({"POST"})
* @Drum(“/resetare”)
* @Sigur(roluri=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
public funcţie resetați acum(Solicitare $request)
{
$params = $cerere->cerere->toate();
if (!array_key_exists("log in", $params)) {
arunca nou Excepție(„Nu s-a dat login”);
}
$login = &$params["log in"];
$em = $ asta->container->get(„doctrine.orm.default_entity_manager”);
$user = $em->getRepository(„NamespaceMyBundle:Utilizator”)->findOneBy(mulțime("log in" => $login));
if ($utilizator == zero) {
reveni $ asta->redirecționare($ asta->generateUrl("log in", mulțime()));
}
$parolă = „myRandowPassword”;
$user->setPassword($ asta->container->get(„security.encoder_factory”)->getEncoder($user)->encodePassword($parola, $user->getSalt()));
$em->persist($utilizator);
$em->flush();
reveni $ asta->redirecționare($ asta->generateUrl("log in", mulțime()));
}
/ **
* @Metodă({"OBȚINE"})
* @Drum(“/schimbare”, nume=”schimbare-parola”)
* @Sigur(roluri=”IS_AUTHENTICATED_FULLY”)
* @Șablon()
*/
public funcţie Schimbare() {
reveni mulțime,
}
/ **
* @Metodă({"POST"})
* @Drum("/Schimbare")
* @Sigur(roluri=”IS_AUTHENTICATED_FULLY”)
* @Șablon()
*/
public funcţie schimba acum(Solicitare $request)
{
$params = $cerere->cerere->toate();
if (!array_key_exists("actual", $params)
|| !array_key_exists("nou", $params)
|| !array_key_exists(„nou2”, $params))
{
reveni mulțime("eroare" => "Va rog completati toate campurile");
}
$em = $ asta->container->get(„doctrine.orm.default_entity_manager”);
$user= $ asta->getUser();
$user_encoders = $ asta->container->get(„security.encoder_factory”)->getEncoder($user);
$user_repository = $em->getRepository(„NamespaceMyBundle:Utilizator”);
$current_password_encoded = $user_encoders->encodePassword($params["actual"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["nou"], $user->getSalt());
if ($user_repository->findOneBy(mulțime("parola" => $parola_curente_codate)) == zero) {
reveni mulțime("eroare" => „Parola actuală este greșită”);
} elseif ($params["nou"] != $params[„nou2”]) {
reveni mulțime("eroare" => „Parola celor două câmpuri nu este aceeași”);
}
$user->setPassword($new_parola_encoded);
$em->persist($utilizator);
$em->flush();
reveni $ asta->redirecționare($ asta->generateUrl(„deconectare”, mulțime()));
}
/ **
* @Metodă({"OBȚINE"})
* @Drum(“/înregistrare”, nume=”înregistrare”)
* @Sigur(roluri=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Șablon()
*/
public funcţie Inregistreaza-te()
{
$form = $ asta->createForm(nou UserType(UserType::REGISTER), nou Utilizator());
reveni mulțime(
"formă" => $form->createView(),
);
}
/ **
* @Metodă({"POST"})
* @Drum("/Inregistreaza-te")
* @Sigur(roluri=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Șablon()
*/
public funcţie înregistrează-te acum(Solicitare $request)
{
$params = $cerere->cerere->toate()[„numele_formularului_meu”];
$form = $ asta->createForm(nou UserType(UserType::REGISTER), nou Utilizator());
$form->submit($cerere);
if (array_key_exists(„parolă_pură”, $params) && array_key_exists(„parolă_clasă2”, $params) && $params[„parolă_pură”] == $params[„parolă_clasă2”]) {
if ($form->isValid()) {
$date = $form->getData();
$date->setPassword($ asta->container->get(„security.encoder_factory”)->getEncoder($date)->encodePassword($params[„parolă_pură”], $date->getSalt()));
$em->persist($date);
$em->flush();
reveni $ asta->redirecționare($ asta->generateUrl("log in", mulțime("mesaj" => „Ați primit un e-mail pentru a vă valida contul. »)));
}
}
reveni mulțime(
„erori” => $params[„parolă_pură”] == $params[„parolă_clasă2”]? $form->getErrors(): mulțime(„Cele două parole trebuie să fie aceleași”),
"formă" => $form->createView(),
);
}
/ **
* @Metodă({"OBȚINE"})
* @Drum(“/activare”, nume=”activare”)
* @Sigur(roluri=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Șablon()
*/
public funcţie activa(Solicitare $request) {
$params = mulțime,
$token = $cerere->interogare->get(« token »);
$em = $ asta->container->get(„doctrine.orm.default_entity_manager”);
$user = $em->getRepository(„NamespaceMyBundle:Utilizator”)->findOneBy(mulțime(« token » => $token));
if ($utilizator != zero) {
$user->setActive(Utilizator::ACTIVE_ACTIVE);
$em->persist($utilizator);
$em->flush();
$params["Activati"] = adevărat;
} altfel {
$params["Activati"] = fals;
}
reveni $params;
}
}
|