Implementujte svoj vlastný SecurityController
Nedávno som pre moju spoločnosť napísal článok o správe používateľov a ich autentifikácii natívne pomocou Symfony2 Core, a teda bez FOSUserBundle. V nadväznosti na tento už bohatý prvý článok som chcel opísať druhú rovnako užitočnú časť, ktorá nám umožní rýchlo nastaviť základné funkcie, a to resetovanie hesla, zmenu hesla, overenie účtu či dokonca registráciu. Akcie sú rovnako dôležité, keď máte systém na správu používateľov.
Nastavte SecurityController
Po prvé, ak ste nesledovali prvý návod, ako nastaviť správu používateľov, odporúčam vám pozrieť sa. Ak ste postupovali podľa riešenia, logicky by ste mali mať SecurityController alebo niečo iné. V mojom prípade mám len tri metódy, z ktorých je reálne použiteľná len jedna.
- prihlásenieAkcia
Táto metóda spája používateľa. - checkAction
Táto metóda vám jednoducho umožňuje deklarovať trasu pre firewall, čo umožňuje používateľovi pripojiť sa na strane servera. - logoutAction
Táto metóda sa používa na deklarovanie trasy pre firewall umožňujúcu odpojenie používateľa.
Otvorte našu platformu novým používateľom
Bolo by obzvlášť zaujímavé, keby sa naši používatelia mohli pripojiť, a teda vopred sa zaregistrovať.
Najprv vygenerujeme formulár s informáciami, ktoré sa chcete spýtať vášho používateľa.
Čo sa týka formulára, ktorý použijete na registráciu svojho používateľa, vedieť, že pole" heslo by nemal byť vo vašej forme. Budete však musieť pridať dve polia " nezmapované aby ste požadované heslo zadali dvakrát.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/ **
* @Metóda({“GET”})
* @Cesta(„/register“, name=“register“)
* @Zabezpečiť(role=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Šablóna()
*/
verejnosť funkcie Registrovať()
{
$form = $ toto->createForm(nový UserType(UserType::REGISTER), nový Používateľ());
návrat rad(
"forma" => $form->createView(),
);
}
|
Potom, keď sa váš používateľ vráti s vyplneným formulárom, budeme ho musieť zaregistrovať alebo odmietnuť jeho súbor :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
|
/ **
* @Metóda({“POST”})
* @Cesta("/Registrovať")
* @Zabezpečiť(role=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Šablóna()
*/
verejnosť funkcie zaregistrujte sa teraz(Žiadosť $request)
{
$params = $request->request->all()["názov_mojho_formulára"];
$form = $ toto->createForm(nový UserType(UserType::REGISTER), nový Používateľ());
$form->submit($požiadavka);
if (pole_key_exists(„obyčajné_heslo“, $params) && array_key_exists(„obyčajné_heslo2“, $params) && $params[„obyčajné_heslo“] == $params[„obyčajné_heslo2“]) {
if ($form->isValid()) {
$data = $form->getData();
$data->setPassword($ toto->container->get("security.encoder_factory")->getEncoder($data)->encodePassword($params[„obyčajné_heslo“], $data->getSalt()));
$em->persist($data);
$em->flush();
návrat $ toto->presmerovať($ toto->generateUrl("Prihlásiť sa", rad("správa" => „Dostali ste e-mail na overenie vášho účtu. »)));
}
}
návrat rad(
"chyby" => $params[„obyčajné_heslo“] == $params[„obyčajné_heslo2“]? $form->getErrors(): rad(„Tieto dve heslá musia byť rovnaké“),
"forma" => $form->createView(),
);
}
|
Tu to rýchlo popíšeme workflow na registráciu nového užívateľa.
- Pozeráme sa ak sú všetky povinné polia zadané správnevrátane dvoch polí „heslo“ a ak sú posledné dve identické.
- Heslo zakódujeme a „nastavíme“ ho v entite.
- V prípade akejkoľvek chyby vraciame formulár s chybou, ktorá by podľa nás mala byť podrobná.
Vytvorte funkciu na obnovenie hesla
Teraz sa váš používateľ môže prihlásiť, ale čo urobíme, ak stratí heslo. Je zrejmé, že sa nechystáme zriadiť kontaktnú emailovú adresu venovanú jej zbytočným operáciám.
Ako ste videli vyššie, zvyčajne deklarujem dve metódy pre každú z mojich funkcií: jedna z mojich metód je zodpovedná za správu zobrazenia vytvoreného na základe požiadavky GET a výsledok žiadosti POST. Tieto dve metódy môžete úplne spojiť do jednej a tej istej metódy.
1
2
3
4
5
6
7
8
9
|
/ **
* @Metóda({“GET”})
* @Cesta(“/reset”, name=”reset”)
* @Zabezpečiť(role=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Šablóna()
*/
verejnosť funkcie obnoviť() {
návrat rad();
}
|
V druhom kroku deklarujeme doplnkovú metódu spravovania požiadaviek 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
|
/ **
* @Metóda({“POST”})
* @Cesta("/reset")
* @Zabezpečiť(role=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
verejnosť funkcie resetNow(Žiadosť $request)
{
$params = $požiadavka->požiadavka->všetky();
if (!array_key_exists("Prihlásiť sa", $params)) {
hod nový výnimka(„Neboli poskytnuté žiadne prihlasovacie údaje“);
}
$login = &$params["Prihlásiť sa"];
$em = $ toto->container->get(“doctrine.orm.default_entity_manager”);
$user = $em->getRepository(„Menový priestorMyBundle:User“)->findOneBy(rad("Prihlásiť sa" => $login));
if ($user == null) {
návrat $ toto->presmerovať($ toto->generateUrl("Prihlásiť sa", rad()));
}
$heslo = "myRandowPassword";
$user->setPassword($ toto->container->get("security.encoder_factory")->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->flush();
// Heslo posielame emailom
návrat $ toto->presmerovať($ toto->generateUrl("Prihlásiť sa", rad()));
}
|
Táto metóda bola navrhnutá tak, aby resetovať heslo používateľa, ktorý poskytol svoje prihlasovacie meno/používateľské meno. V mojom prípade bolo heslo následne zaslané emailom. Dovolím si pridať tú galantnú líniu.
- Takže ideme vyhľadávať užívateľa.
- Vygenerujeme heslo že používateľa informujeme, keď sa zakóduje podľa pravidiel, ktoré ste definovali.
Nastavte zmenu hesla
V tomto bode si náš používateľ môže vygenerovať nové heslo, ak by sa stratilo, ale v prípade, že ho chce len zmeniť, potrebujeme bránu na definovanie brány.
1
2
3
4
5
6
7
8
9
|
/ **
* @Metóda({“GET”})
* @Cesta(„/change“, name=“change-password“)
* @Zabezpečiť(role=”IS_AUTHENTICATED_FULLY”)
* @Šablóna()
*/
verejnosť funkcie zmena() {
návrat rad();
}
|
Tu je kód na vygenerovanie zobrazenia. Najprv budete musieť zadať svoje staré heslo a potom dvakrát zadať nové heslo. Druhýkrát potvrdenie.
Teraz uvidíme kód reseter heslo. THE proces je podobné generovaniu nového náhodného hesla.
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
|
/ **
* @Metóda({“POST”})
* @Cesta("/zmena")
* @Zabezpečiť(role=”IS_AUTHENTICATED_FULLY”)
* @Šablóna()
*/
verejnosť funkcie zmeniť teraz(Žiadosť $request)
{
$params = $požiadavka->požiadavka->všetky();
if (!array_key_exists("aktuálne", $params)
|| !array_key_exists("Nový", $params)
|| !array_key_exists("nové2", $params))
{
návrat rad("chyba" => “Vyplňte všetky polia”);
}
$em = $ toto->container->get(“doctrine.orm.default_entity_manager”);
$user= $ toto->getUser();
$user_encoders = $ toto->container->get("security.encoder_factory")->getEncoder($user);
$user_repository = $em->getRepository(„Menový priestorMyBundle:User“);
$current_password_encoded = $user_encoders->encodePassword($params["aktuálne"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["Nový"], $user->getSalt());
if ($user_repository->findOneBy(rad("heslo" => $current_password_encoded)) == null) {
návrat rad("chyba" => „Aktuálne heslo je nesprávne“);
} ináč Ak ($params["Nový"] != $params["nové2"]) {
návrat rad("chyba" => "Heslo dvoch polí nie je rovnaké");
}
$user->setPassword($new_password_encoded);
$em->persist($user);
$em->flush();
návrat $ toto->presmerovať($ toto->generateUrl("odhlásiť sa", rad()));
}
|
Ak si prečítate kód 1 minútu, uvidíte, že tento je obzvlášť jednoduchý.
- Najprv skontrolujeme, či boli správne zadané tri polia (staré heslo, nové heslo a potvrdenie).
- On zadajte heslo prúd a porovnáme s aktuálnym heslomv databáze, aby ste zistili, či zodpovedá starému zadanému heslu.
- Skontrolujeme, či sú „dve“ nové heslá identický.
- Zadajte nové heslo a tlačiť v entite.
Aktivácia jeho účtu
V iných nie je táto funkcia podrobne opísaná úryvky vyššie. Jeho účelom je odblokovať používateľa, ktorý sa práve zaregistroval, keď si napríklad overil svoj email. Táto funkcionalita je vyvinutá takmer na všetkých platformách, ktoré poznáme z niekoľkých dôvodov. Ak chcete nastaviť blokovanie používateľa, možno budete musieť implementovať aj poskytovateľa.
- blok/limit účty falošný a spam.
- skontrolovať že používateľ vyplnil e-mailovú adresu, ktorá sa na prvý pohľad javí ako použiteľná.
- odstrániť účty, ktoré neboli po určitom čase overené.
Workflow
- Používateľ sa zaregistruje. Jeho účet je potom zablokovaný prostredníctvom poľa špecifického pre vás. Toto pole by mu malo zabrániť v pripojení, pokiaľ toto pole označuje, že účet je zakázaný.
1
2
3
4
5
6
7
8
|
// NamespaceMyBundleEntityUser
trieda užívateľ {
verejnosť funkcie __konštrukcia() {
$ toto->token = hash("sha512", uniqid());
}
...
}
|
1
|
$user->setEnabled(nepravdivý);
|
- Používateľ dostal e-mail, keď bol jeho profil spláchnuť v databáze. Tento e-mail musí byť súčasťou vami vygenerovanej adresy.
Na tejto ceste a token alebo musí byť uvedený jedinečný identifikátor, ktorý umožní nájsť príslušného používateľa. Odporúčam vám použiť UUID4, ktorý má byť náhodný. Nájdete tu zoznam UUID, ako aj popis všetkých verzií.
1
2
3
4
|
/ **
* @Cesta("/aktivovať", meno = "aktivovať")
*/
verejnosť funkcie aktivovaný() {…}
|
1
|
$ toto->generateUrl("Aktivovať", rad(« token » => $user->getToken()), pravdivý);
|
Mali by ste mať takúto adresu URL.
1
|
http://názov hostiteľa/aktivovať?token=myUniqueToken
|
- Používateľ otvorí svoj e-mail a pokúsi sa aktivovať svoj účet kliknutím na uvedený odkaz. Potom vstúpime do procesu nižšie.
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
|
/ **
* @Metóda({“GET”})
* @Cesta("/aktivovať", meno = "aktivovať")
* @Zabezpečiť(role=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Šablóna()
*/
verejnosť funkcie aktivovaný(Žiadosť $request) {
$params = rad();
$token = $request->query->get(« token »);
$em = $ toto->container->get(“doctrine.orm.default_entity_manager”);
$user = $em->getRepository(„Menový priestorMyBundle:User“)->findOneBy(rad(« token » => $token));
if ($user != null) {
$user->setEnabled(pravdivý);
$em->persist($user);
$em->flush();
$params["Aktivovať"🇧🇷 pravdivý;
} inak {
$params["Aktivovať"🇧🇷 nepravdivý;
}
návrat $params;
}
|
S týmto procesom by ste nemali mať problém povoliť overenie používateľského účtu.
Tento ekvivalentný kód nájdete v tejto podstate.
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
|
použitie JMSSecurityExtraBundlevysvetlivkabezpečne;
použitie SensioBalíkFrameworkExtraBundlekonfiguráciaMetóda;
použitie SensioBalíkFrameworkExtraBundlekonfiguráciaCesta;
použitie SensioBalíkFrameworkExtraBundlekonfiguráciašablóna;
použitie SymfonyBalíkFrameworkBundlekontrolórkontrolór;
použitie SymfonyZložkaHttpFoundationžiadosť;
použitie SymfonyZložkazabezpečeniaJadroSecurityContext;
trieda SecurityController predlžuje kontrolór
{
/ **
* @Metóda({“GET”})
* @Cesta(“/login”, meno=”login”)
* @Šablóna()
*/
verejnosť funkcie Prihlásiť sa(Žiadosť $request)
{
$požiadavka = $ toto->getRequest();
$session = $request->getSession();
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} inak {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
$params = rad(
„priezvisko_používateľské meno“ => $session->get(SecurityContext::LAST_USERNAME),
"chyba" => $chyba,
"správa" => $request->get("správa"),
);
if ($request->isXmlHttpRequest()) {
návrat $ toto->render(„Hlavný balík GCDirectory:Security:login-ajax.html.twig“, $params);
}
návrat $params;
}
/ **
* @Metóda({“POST”})
* @Cesta(“/login_check”, name=”login_check”)
*/
verejnosť funkcie skontrolovať()
{
hod nový RuntimeException('Musíte nakonfigurovať kontrolnú cestu, ktorú má spracovať brána firewall, pomocou formulára_login v konfigurácii vašej bezpečnostnej brány firewall.');
}
/ **
* @Metóda({“GET”})
* @Cesta(“/logout”, name=”logout”)
*/
verejnosť funkcie odhlásiť()
{
hod nový RuntimeException('Musíte aktivovať odhlásenie v konfigurácii bezpečnostnej brány firewall.');
}
/ **
* @Metóda({“GET”})
* @Cesta(“/reset”, name=”reset”)
* @Zabezpečiť(role=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Šablóna()
*/
verejnosť funkcie obnoviť() {
návrat rad();
}
/ **
* @Metóda({“POST”})
* @Cesta("/reset")
* @Zabezpečiť(role=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
verejnosť funkcie resetNow(Žiadosť $request)
{
$params = $požiadavka->požiadavka->všetky();
if (!array_key_exists("Prihlásiť sa", $params)) {
hod nový výnimka(„Neboli poskytnuté žiadne prihlasovacie údaje“);
}
$login = &$params["Prihlásiť sa"];
$em = $ toto->container->get(“doctrine.orm.default_entity_manager”);
$user = $em->getRepository(„Menový priestorMyBundle:User“)->findOneBy(rad("Prihlásiť sa" => $login));
if ($user == null) {
návrat $ toto->presmerovať($ toto->generateUrl("Prihlásiť sa", rad()));
}
$heslo = "myRandowPassword";
$user->setPassword($ toto->container->get("security.encoder_factory")->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->flush();
návrat $ toto->presmerovať($ toto->generateUrl("Prihlásiť sa", rad()));
}
/ **
* @Metóda({“GET”})
* @Cesta(„/change“, name=“change-password“)
* @Zabezpečiť(role=”IS_AUTHENTICATED_FULLY”)
* @Šablóna()
*/
verejnosť funkcie zmena() {
návrat rad();
}
/ **
* @Metóda({“POST”})
* @Cesta("/zmena")
* @Zabezpečiť(role=”IS_AUTHENTICATED_FULLY”)
* @Šablóna()
*/
verejnosť funkcie zmeniť teraz(Žiadosť $request)
{
$params = $požiadavka->požiadavka->všetky();
if (!array_key_exists("aktuálne", $params)
|| !array_key_exists("Nový", $params)
|| !array_key_exists("nové2", $params))
{
návrat rad("chyba" => “Vyplňte všetky polia”);
}
$em = $ toto->container->get(“doctrine.orm.default_entity_manager”);
$user= $ toto->getUser();
$user_encoders = $ toto->container->get("security.encoder_factory")->getEncoder($user);
$user_repository = $em->getRepository(„Menový priestorMyBundle:User“);
$current_password_encoded = $user_encoders->encodePassword($params["aktuálne"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["Nový"], $user->getSalt());
if ($user_repository->findOneBy(rad("heslo" => $current_password_encoded)) == null) {
návrat rad("chyba" => „Aktuálne heslo je nesprávne“);
} ináč Ak ($params["Nový"] != $params["nové2"]) {
návrat rad("chyba" => "Heslo dvoch polí nie je rovnaké");
}
$user->setPassword($new_password_encoded);
$em->persist($user);
$em->flush();
návrat $ toto->presmerovať($ toto->generateUrl("odhlásiť sa", rad()));
}
/ **
* @Metóda({“GET”})
* @Cesta(„/register“, name=“register“)
* @Zabezpečiť(role=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Šablóna()
*/
verejnosť funkcie Registrovať()
{
$form = $ toto->createForm(nový UserType(UserType::REGISTER), nový Používateľ());
návrat rad(
"forma" => $form->createView(),
);
}
/ **
* @Metóda({“POST”})
* @Cesta("/Registrovať")
* @Zabezpečiť(role=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Šablóna()
*/
verejnosť funkcie zaregistrujte sa teraz(Žiadosť $request)
{
$params = $request->request->all()["názov_mojho_formulára"];
$form = $ toto->createForm(nový UserType(UserType::REGISTER), nový Používateľ());
$form->submit($požiadavka);
if (pole_key_exists(„obyčajné_heslo“, $params) && array_key_exists(„obyčajné_heslo2“, $params) && $params[„obyčajné_heslo“] == $params[„obyčajné_heslo2“]) {
if ($form->isValid()) {
$data = $form->getData();
$data->setPassword($ toto->container->get("security.encoder_factory")->getEncoder($data)->encodePassword($params[„obyčajné_heslo“], $data->getSalt()));
$em->persist($data);
$em->flush();
návrat $ toto->presmerovať($ toto->generateUrl("Prihlásiť sa", rad("správa" => „Dostali ste e-mail na overenie vášho účtu. »)));
}
}
návrat rad(
"chyby" => $params[„obyčajné_heslo“] == $params[„obyčajné_heslo2“]? $form->getErrors(): rad(„Tieto dve heslá musia byť rovnaké“),
"forma" => $form->createView(),
);
}
/ **
* @Metóda({“GET”})
* @Cesta("/aktivovať", meno = "aktivovať")
* @Zabezpečiť(role=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Šablóna()
*/
verejnosť funkcie aktivovaný(Žiadosť $request) {
$params = rad();
$token = $request->query->get(« token »);
$em = $ toto->container->get(“doctrine.orm.default_entity_manager”);
$user = $em->getRepository(„Menový priestorMyBundle:User“)->findOneBy(rad(« token » => $token));
if ($user != null) {
$user->setActive(User::ACTIVE_ACTIVE);
$em->persist($user);
$em->flush();
$params["Aktivovať"🇧🇷 pravdivý;
} inak {
$params["Aktivovať"🇧🇷 nepravdivý;
}
návrat $params;
}
}
|