Zbatoni kontrolluesin tuaj të sigurisë
Kohët e fundit kam shkruar një artikull për kompaninë time mbi menaxhimin e përdoruesve dhe vërtetimin e tyre duke përdorur Symfony2 Core në mënyrë origjinale, dhe për këtë arsye pa FOSUserBundle. Pas këtij artikulli të parë tashmë të pasur, doja të përshkruaj një pjesë të dytë po aq të dobishme që do të na lejojë të konfigurojmë shpejt funksionet thelbësore, domethënë rivendosjen e fjalëkalimit, ndryshimin e fjalëkalimit, vërtetimin e llogarisë tuaj apo edhe regjistrimin. Veprimet po aq thelbësore kur keni një sistem që menaxhon përdoruesit.
Vendosni një Kontrollues të Sigurisë
Së pari, nëse nuk e keni ndjekur udhëzuesin e parë se si të vendosni menaxhimin e përdoruesve, ju këshilloj të hidhni një sy. Nëse keni ndjekur zgjidhjen, logjikisht duhet të keni një SecurityController ose diçka tjetër. Në rastin tim, unë kam vetëm tre metoda, vetëm njëra prej të cilave është vërtet e përdorshme.
- loginVeprim
Kjo metodë lidh një përdorues. - kontrolloveprim
Kjo metodë thjesht ju lejon të deklaroni një rrugë për murin e zjarrit, duke lejuar një përdorues të lidhet në anën e serverit. - dalje Veprimi
Kjo metodë përdoret për të deklaruar një rrugë për murin e zjarrit që lejon një përdorues të shkëputet.
Hapni platformën tonë për përdoruesit e rinj
Do të ishte veçanërisht interesante nëse përdoruesit tanë mund të lidhen, dhe për këtë arsye të jenë në gjendje të regjistrohen paraprakisht.
Së pari, ne gjenerojmë formularin me informacionin që dëshironi të kërkoni nga përdoruesi juaj.
Në lidhje me formularin që do të përdorni për të regjistruar përdoruesin tuaj, e di se fusha " Fjalëkalimi nuk duhet të jetë në formën tuaj. Sidoqoftë, do t'ju duhet të shtoni dy fusha " jo të hartësuar në mënyrë që të futet dy herë fjalëkalimi i dëshiruar.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/ **
* @Metodë({"MARR"})
* @Rruga(“/regjistrohu”, emri=”regjistrohu”)
* @Secure(rolet=”IS_AUTHENTICATED_ANONYMË”)
* @Template()
*/
publik funksion regjistruar()
{
$form = $ kjo->krijoForm(i ri Lloji i Përdoruesit (Lloji i Përdoruesit::REGJISTRI), i ri Përdoruesi ());
kthim grup(
"formë" => $form->createView(),
);
}
|
Pastaj, kur përdoruesi juaj kthehet me formularin e tij të plotësuar, ne do të duhet ta regjistrojmë ose ta refuzojmë dosjen e tij :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”})
* @Rruga(“/regjistrohu”)
* @Secure(rolet=”IS_AUTHENTICATED_ANONYMË”)
* @Template()
*/
publik funksion Regjistrohu Tani(Kërko $kërkesë)
{
$params = $kërkim->kërkim->të gjitha()["Emri_of_formës sime"];
$form = $ kjo->krijoForm(i ri Lloji i Përdoruesit (Lloji i Përdoruesit::REGJISTRI), i ri Përdoruesi ());
$form->submit($kërkesë);
if (kyç_array_ekziston("fjalëkalim_i thjeshtë", $params) && array_key_exists("plain_password2", $params) && $params["fjalëkalim_i thjeshtë"] == $params["plain_password2"]) {
if ($form->isValid()) {
$data = $form->getData();
$data->setPassword($ kjo-> enë-> merrni("security.encoder_factory")->getEncoder($data)->encodePassword($params["fjalëkalim_i thjeshtë"], $data->getSalt()));
$em->persist($data);
$em->flush();
kthim $ kjo-> ridrejto($ kjo->generateUrl("hyrja", grup("mesazh" => “Ju keni marrë një email për të vërtetuar llogarinë tuaj. »)));
}
}
kthim grup(
"gabime" => $params["fjalëkalim_i thjeshtë"] == $params["plain_password2"]? $form->getErrors(): grup("Dy fjalëkalimet duhet të jenë të njëjta"),
"formë" => $form->createView(),
);
}
|
Këtu do të detajojmë shpejt workflow për të regjistruar një përdorues të ri.
- Ne shikojmë nëse të gjitha fushat e kërkuara janë futur saktë, duke përfshirë dy fushat "fjalëkalim", dhe nëse dy të fundit janë identike.
- Ne kodojmë fjalëkalimin dhe e “vendosim” në entitet.
- Në rast të ndonjë gabimi e kthejmë formularin me gabimin që mendojmë se duhet të detajohet.
Krijoni një veçori për të rivendosur fjalëkalimin tuaj
Tani përdoruesi juaj mund të identifikohet, por çfarë do të bëjmë nëse ai humbet fjalëkalimin e tij. Është e qartë se ne nuk do të krijojmë një adresë emaili kontakti kushtuar operacioneve të saj të padobishme.
Siç e keni parë më lart, unë zakonisht deklaroj dy metoda për secilën nga veçoritë e mia: një nga metodat e mia është përgjegjëse për menaxhimin e pamjes së krijuar pas një kërkese. GET dhe si rezultat i një kërkese POST. Ju mund t'i bashkoni absolutisht këto dy metoda në një dhe të njëjtën metodë.
1
2
3
4
5
6
7
8
9
|
/ **
* @Metodë({"MARR"})
* @Rruga(“/rivendos”, emri=”rivendos”)
* @Secure(rolet=”IS_AUTHENTICATED_ANONYMË”)
* @Template()
*/
publik funksion rivendosni() {
kthim grup();
}
|
Në një hap të dytë, ne do të deklarojmë metodën plotësuese të menaxhimit të kërkesave 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”})
* @Rruga(“/rivendos”)
* @Secure(rolet=”IS_AUTHENTICATED_ANONYMË”)
*/
publik funksion rivendos Tani(Kërko $kërkesë)
{
$params = $kërkim->kërkim->të gjitha();
if (!array_key_exists("hyrja", $params)) {
hedh i ri përjashtim("Nuk është dhënë asnjë hyrje");
}
$login = &$params["hyrja"];
$em = $ kjo-> enë-> merrni("doctrine.orm.default_entity_manager");
$user = $em->getRepository("NamespaceMyBundle:Përdoruesi")->findOneBy(grup("hyrja" => $login));
if ($user == null) {
kthim $ kjo-> ridrejto($ kjo->generateUrl("hyrja", grup()));
}
$fjalëkalim = "myRandowPassword";
$user->setPassword($ kjo-> enë-> merrni("security.encoder_factory")->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->flush();
// Ne dërgojmë fjalëkalimin me email
kthim $ kjo-> ridrejto($ kjo->generateUrl("hyrja", grup()));
}
|
Kjo metodë është krijuar për të rivendosur fjalëkalimin e një përdoruesi që ka dhënë të tijën hyrje/emri i përdoruesit. Në rastin tim, fjalëkalimi u dërgua më pas me email. Unë do t'ju lejoj të shtoni atë linjë galante.
- Kështu që ne po shkojmë përdoruesi i kërkimit.
- Ne krijojmë një fjalëkalim që ne vijmë të informojmë përdoruesin pasi ai të ketë koduar sipas rregullave që ju keni përcaktuar.
Konfiguro ndryshimin e fjalëkalimit
Në këtë pikë, përdoruesi ynë mund të gjenerojë një fjalëkalim të ri nëse ai humbet, por në rast se ai thjesht dëshiron ta ndryshojë atë, ne kemi nevojë për një portë për të përcaktuar një portë.
1
2
3
4
5
6
7
8
9
|
/ **
* @Metodë({"MARR"})
* @Rruga(“/ndrysho”, emri=”ndrysho-fjalëkalimin”)
* @Secure(rolet=”IS_AUTHENTICATED_FULLY”)
* @Template()
*/
publik funksion ndryshim() {
kthim grup();
}
|
Këtu është kodi për të gjeneruar pamjen. Së pari, do të duhet të futni fjalëkalimin tuaj të vjetër, më pas futni fjalëkalimin tuaj të ri dy herë. Hera e dytë është konfirmimi.
Tani do të shohim kodin për të rivendosës fjalëkalimin. THE proces është e ngjashme me gjenerimin e një fjalëkalimi të ri të rastësishëm.
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”})
* @Rruga(“/ndrysho”)
* @Secure(rolet=”IS_AUTHENTICATED_FULLY”)
* @Template()
*/
publik funksion ndrysho Tani(Kërko $kërkesë)
{
$params = $kërkim->kërkim->të gjitha();
if (!array_key_exists("aktuale", $params)
|| !array_key_exists("i ri", $params)
|| !array_key_exists("i ri 2", $params))
{
kthim grup("gabim" => "Ju lutemi plotësoni të gjitha fushat");
}
$em = $ kjo-> enë-> merrni("doctrine.orm.default_entity_manager");
$përdorues = $ kjo->getUser();
$user_encoders = $ kjo-> enë-> merrni("security.encoder_factory")->getEncoder($user);
$user_repository = $em->getRepository("NamespaceMyBundle:Përdoruesi");
$current_password_encoded = $user_encoders->encodePassword($params["aktuale"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["i ri"], $user->getSalt());
if ($user_repository->findOneBy(grup("fjalëkalim" => $current_password_encoded)) == null) {
kthim grup("gabim" => "Fjalëkalimi aktual është i gabuar");
} tjeter nese ($params["i ri"] != $params["i ri 2"]) {
kthim grup("gabim" => "Fjalëkalimi i dy fushave nuk është i njëjtë");
}
$user->setPassword($new_password_encoded);
$em->persist($user);
$em->flush();
kthim $ kjo-> ridrejto($ kjo->generateUrl("shkyç", grup()));
}
|
Nëse merrni 1 minutë për të lexuar kodin, do të shihni se ky është veçanërisht i thjeshtë.
- Së pari, kontrollojmë nëse tre fushat (fjalëkalimi i vjetër, fjalëkalimi i ri dhe konfirmimi) janë futur saktë.
- On futni fjalëkalimin aktuale dhe ne e krahasojmë atë me fjalëkalimin aktualment në bazën e të dhënave për të parë nëse korrespondon me fjalëkalimin e vjetër të futur.
- Ne kontrollojmë nëse janë "dy" fjalëkalimet e reja identik.
- Futni fjalëkalimin e ri dhe shtytje në entitet.
Aktivizimi i llogarisë së tij
Kjo veçori nuk është e detajuar në mënyrë të përsosur në të tjera copra sipër. Qëllimi i tij është të zhbllokojë një përdorues që sapo është regjistruar, kur ai ka vërtetuar emailin e tij për shembull. Ky funksionalitet është zhvilluar pothuajse në të gjitha platformat që njohim për disa arsye. Për të vendosur një bllokim të një përdoruesi, mund t'ju duhet gjithashtu të zbatoni një ofrues.
- Bllokoj/Limit llogaritë falso dhe bllokuara.
- kontrolloj se përdoruesi ka plotësuar një adresë e-mail që duket e përdorshme në shikim të parë.
- heq llogaritë që nuk janë vërtetuar pas një periudhe të caktuar kohore.
Rrjedha
- Një përdorues regjistrohet. Llogaria e tij më pas bllokohet nëpërmjet një fushe specifike për ju. Kjo fushë duhet ta pengojë atë të lidhet për sa kohë që kjo fushë tregon se llogaria është e çaktivizuar.
1
2
3
4
5
6
7
8
|
// NamespaceMyBundleEntityUser
klasë Përdorues {
publik funksion __ndërtoj() {
$ kjo->token = hash("sha512", uniqid());
}
...
}
|
1
|
$user->setEnabled(i rremë);
|
- Përdoruesi mori një email kur profili i tij ishte skuqem në bazën e të dhënave. Ky email duhet të jetë pjesë e një adrese që krijoni.
Në këtë rrugë, një token ose duhet të jepet një identifikues unik duke lejuar gjetjen e përdoruesit në fjalë. Unë ju këshilloj të përdorni një UUID4 i cili synohet të jetë i rastësishëm. Mund të gjeni listën e UUID-ve si dhe përshkrimin e të gjitha versioneve.
1
2
3
4
|
/ **
* @Rruga(“/aktivizo”, emri=”aktivizo”)
*/
publik funksion aktivizoj() {…}
|
1
|
$ kjo->generateUrl("aktivizo", grup(« token » => $user->merrToken()), i vërtetë);
|
Ju duhet të keni një URL si kjo.
1
|
http://emri i hostit/aktivizohet?token=myUniqueToken
|
- Përdoruesi hap emailin e tij dhe përpiqet të aktivizojë llogarinë e tij duke klikuar në lidhjen e dhënë. Më pas hyjmë në procesin e mëposhtëm.
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ë({"MARR"})
* @Rruga(“/aktivizo”, emri=”aktivizo”)
* @Secure(rolet=”IS_AUTHENTICATED_ANONYMË”)
* @Template()
*/
publik funksion aktivizoj(Kërko $kërkesë) {
$params = grup();
$token = $request->query->merr(« token »);
$em = $ kjo-> enë-> merrni("doctrine.orm.default_entity_manager");
$user = $em->getRepository("NamespaceMyBundle:Përdoruesi")->findOneBy(grup(« token » => $token));
if ($user != null) {
$user->setEnabled(i vërtetë);
$em->persist($user);
$em->flush();
$params["aktivizo"] = = i vërtetë;
} tjetër {
$params["aktivizo"] = = i rremë;
}
kthim $params;
}
|
Me këtë proces nuk duhet të keni asnjë problem për të aktivizuar vërtetimin e llogarisë së përdoruesit.
Ju mund ta gjeni këtë kod ekuivalent në këtë 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
|
përdorim JMSSecurity ExtraBundleshënimSiguroj;
përdorim SensioDengFrameworkExtraBundleKonfiguracionMetoda e dërgesës;
përdorim SensioDengFrameworkExtraBundleKonfiguracionRrugë;
përdorim SensioDengFrameworkExtraBundleKonfiguracionShabllon;
përdorim SymfonyDengFramework BundleKontrolluesKontrollues;
përdorim SymfonyKomponentHttpFoundationKërkesa;
përdorim SymfonyKomponentSiguriBërthamëKonteksti i Sigurisë;
klasë Kontrolluesi i Sigurisë shtrihet Kontrollues
{
/ **
* @Metodë({"MARR"})
* @Rruga(“/login”, emri=”hyrja”)
* @Template()
*/
publik funksion hyrje(Kërko $kërkesë)
{
$kërkesë = $ kjo->getRequest();
$sesion = $kërkim->getSession();
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$gabim = $kërkim->atribute->merr(SecurityContext::AUTHENTICATION_ERROR);
} tjetër {
$gabim = $sesion->merr(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
$params = grup(
"emri_përdorues" => $session->merr(SecurityContext::LAST_USERNAME),
"gabim" => $gabim,
"mesazh" => $kërkim->merr("mesazh"),
);
if ($request->isXmlHttpRequest()) {
kthim $ kjo-> render ("GCDirectoryMainBundle:Security:login-ajax.html.twig", $params);
}
kthim $params;
}
/ **
* @Metodë({“POST”})
* @Rruga(“/login_check”, emri=”login_check”)
*/
publik funksion shikoni()
{
hedh i ri Përjashtim i kohës së ekzekutimit ("Duhet të konfiguroni shtegun e kontrollit që do të trajtohet nga muri i zjarrit duke përdorur form_login në konfigurimin e murit të zjarrit të sigurisë.");
}
/ **
* @Metodë({"MARR"})
* @Rruga(“/logout”, emri=”dalja”)
*/
publik funksion logout()
{
hedh i ri Përjashtim i kohës së ekzekutimit ("Duhet të aktivizoni daljen në konfigurimin e murit të zjarrit të sigurisë".);
}
/ **
* @Metodë({"MARR"})
* @Rruga(“/rivendos”, emri=”rivendos”)
* @Secure(rolet=”IS_AUTHENTICATED_ANONYMË”)
* @Template()
*/
publik funksion rivendosni() {
kthim grup();
}
/ **
* @Metodë({“POST”})
* @Rruga(“/rivendos”)
* @Secure(rolet=”IS_AUTHENTICATED_ANONYMË”)
*/
publik funksion rivendos Tani(Kërko $kërkesë)
{
$params = $kërkim->kërkim->të gjitha();
if (!array_key_exists("hyrja", $params)) {
hedh i ri përjashtim("Nuk është dhënë asnjë hyrje");
}
$login = &$params["hyrja"];
$em = $ kjo-> enë-> merrni("doctrine.orm.default_entity_manager");
$user = $em->getRepository("NamespaceMyBundle:Përdoruesi")->findOneBy(grup("hyrja" => $login));
if ($user == null) {
kthim $ kjo-> ridrejto($ kjo->generateUrl("hyrja", grup()));
}
$fjalëkalim = "myRandowPassword";
$user->setPassword($ kjo-> enë-> merrni("security.encoder_factory")->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->flush();
kthim $ kjo-> ridrejto($ kjo->generateUrl("hyrja", grup()));
}
/ **
* @Metodë({"MARR"})
* @Rruga(“/ndrysho”, emri=”ndrysho-fjalëkalimin”)
* @Secure(rolet=”IS_AUTHENTICATED_FULLY”)
* @Template()
*/
publik funksion ndryshim() {
kthim grup();
}
/ **
* @Metodë({“POST”})
* @Rruga(“/ndrysho”)
* @Secure(rolet=”IS_AUTHENTICATED_FULLY”)
* @Template()
*/
publik funksion ndrysho Tani(Kërko $kërkesë)
{
$params = $kërkim->kërkim->të gjitha();
if (!array_key_exists("aktuale", $params)
|| !array_key_exists("i ri", $params)
|| !array_key_exists("i ri 2", $params))
{
kthim grup("gabim" => "Ju lutemi plotësoni të gjitha fushat");
}
$em = $ kjo-> enë-> merrni("doctrine.orm.default_entity_manager");
$përdorues = $ kjo->getUser();
$user_encoders = $ kjo-> enë-> merrni("security.encoder_factory")->getEncoder($user);
$user_repository = $em->getRepository("NamespaceMyBundle:Përdoruesi");
$current_password_encoded = $user_encoders->encodePassword($params["aktuale"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["i ri"], $user->getSalt());
if ($user_repository->findOneBy(grup("fjalëkalim" => $current_password_encoded)) == null) {
kthim grup("gabim" => "Fjalëkalimi aktual është i gabuar");
} tjeter nese ($params["i ri"] != $params["i ri 2"]) {
kthim grup("gabim" => "Fjalëkalimi i dy fushave nuk është i njëjtë");
}
$user->setPassword($new_password_encoded);
$em->persist($user);
$em->flush();
kthim $ kjo-> ridrejto($ kjo->generateUrl("shkyç", grup()));
}
/ **
* @Metodë({"MARR"})
* @Rruga(“/regjistrohu”, emri=”regjistrohu”)
* @Secure(rolet=”IS_AUTHENTICATED_ANONYMË”)
* @Template()
*/
publik funksion regjistruar()
{
$form = $ kjo->krijoForm(i ri Lloji i Përdoruesit (Lloji i Përdoruesit::REGJISTRI), i ri Përdoruesi ());
kthim grup(
"formë" => $form->createView(),
);
}
/ **
* @Metodë({“POST”})
* @Rruga(“/regjistrohu”)
* @Secure(rolet=”IS_AUTHENTICATED_ANONYMË”)
* @Template()
*/
publik funksion Regjistrohu Tani(Kërko $kërkesë)
{
$params = $kërkim->kërkim->të gjitha()["Emri_of_formës sime"];
$form = $ kjo->krijoForm(i ri Lloji i Përdoruesit (Lloji i Përdoruesit::REGJISTRI), i ri Përdoruesi ());
$form->submit($kërkesë);
if (kyç_array_ekziston("fjalëkalim_i thjeshtë", $params) && array_key_exists("plain_password2", $params) && $params["fjalëkalim_i thjeshtë"] == $params["plain_password2"]) {
if ($form->isValid()) {
$data = $form->getData();
$data->setPassword($ kjo-> enë-> merrni("security.encoder_factory")->getEncoder($data)->encodePassword($params["fjalëkalim_i thjeshtë"], $data->getSalt()));
$em->persist($data);
$em->flush();
kthim $ kjo-> ridrejto($ kjo->generateUrl("hyrja", grup("mesazh" => “Ju keni marrë një email për të vërtetuar llogarinë tuaj. »)));
}
}
kthim grup(
"gabime" => $params["fjalëkalim_i thjeshtë"] == $params["plain_password2"]? $form->getErrors(): grup("Dy fjalëkalimet duhet të jenë të njëjta"),
"formë" => $form->createView(),
);
}
/ **
* @Metodë({"MARR"})
* @Rruga(“/aktivizo”, emri=”aktivizo”)
* @Secure(rolet=”IS_AUTHENTICATED_ANONYMË”)
* @Template()
*/
publik funksion aktivizoj(Kërko $kërkesë) {
$params = grup();
$token = $request->query->merr(« token »);
$em = $ kjo-> enë-> merrni("doctrine.orm.default_entity_manager");
$user = $em->getRepository("NamespaceMyBundle:Përdoruesi")->findOneBy(grup(« token » => $token));
if ($user != null) {
$user->setActive(Përdoruesi::ACTIVE_ACTIVE);
$em->persist($user);
$em->flush();
$params["aktivizo"] = = i vërtetë;
} tjetër {
$params["aktivizo"] = = i rremë;
}
kthim $params;
}
}
|