Implementer din egen SecurityController
Webbyrå » Digitale nyheter » Implementer din egen SecurityController

Implementer din egen SecurityController

Jeg skrev nylig en artikkel for firmaet mitt om administrasjon av brukere og deres autentisering ved å bruke Symfony2 Core naturlig, og derfor uten FOSUserBundle. Etter denne allerede rike første artikkelen, ønsket jeg å beskrive en like nyttig andre del som lar oss raskt sette opp de essensielle funksjonene, nemlig å tilbakestille passordet ditt, endre passordet ditt, validere kontoen din eller til og med registrere deg. Handlinger like viktige når du har et system som administrerer brukere.

Sett opp en sikkerhetskontroller

Først, hvis du ikke har fulgt den første opplæringen om hvordan du setter opp brukeradministrasjon, anbefaler jeg deg å ta en titt. Hvis du fulgte løsningen, burde du logisk sett ha en SecurityController eller noe annet. I mitt tilfelle har jeg bare tre metoder, hvorav bare en er virkelig brukbar.

  1. loginAction
    Denne metoden kobler en bruker.
  2. sjekkHandling
    Denne metoden lar deg ganske enkelt deklarere en rute for brannmuren, slik at en bruker kan koble til på serversiden.
  3. Logg utAksjon
    Denne metoden brukes til å deklarere en rute for brannmuren slik at en bruker kan kobles fra.

Åpne vår plattform for nye brukere

Det ville vært spesielt interessant om våre brukere kunne koble seg til, og derfor kunne registrere seg på forhånd.

Først genererer vi skjemaet med informasjonen du vil spørre brukeren din om.

Når det gjelder skjemaet du vil bruke for å registrere brukeren din, vet at feltet " passord bør ikke være i din form. Du må imidlertid legge til to felt " ikke kartlagt for å få inn ønsket passord to ganger.

1
2
3
4
5
6
7
8
9
10
11
12
13
/ **
 * @Metode({"FÅ"})
 * @Vei("/register", navn="register")
 * @Sikre(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
 * @Mal()
 */
offentlig funksjon registrere()
{
    $form = $ dette->opprett skjema(nytt UserType(UserType::REGISTER), nytt Bruker());
    retur matrise(
        "form" => $form->createView(),
        );
}

Så er det når brukeren din kommer tilbake med skjemaet fylt ut at vi må registrere ham eller avvise filen hans :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
/ **
* @Metode({"POST"})
* @Vei("/registrere")
* @Sikre(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Mal()
*/
offentlig funksjon Registrer deg nå(Be om $request)
{
$params = $request->request->all()[«navn_på_min_skjema»];
$form = $ dette->opprett skjema(nytt UserType(UserType::REGISTER), nytt Bruker());
$form->submit($request);
if (array_key_exists(«vanlig_passord», $params) && array_key_exists(«vanlig_passord2», $params) && $params[«vanlig_passord»] == $params[«vanlig_passord2»]) {
if ($form->isValid()) {
$data = $form->getData();
$data->setPassword($ dette->beholder->få(«security.encoder_factory»)->getEncoder($data)->encodePassword($params[«vanlig_passord»], $data->getSalt()));
$em->persist($data);
$em->flush();
retur $ dette->omdirigere($ dette->genererUrl("Logg Inn", matrise(" beskjed " => "Du har mottatt en e-post for å bekrefte kontoen din. »)));
}
}
retur matrise(
"feil" => $params[«vanlig_passord»] == $params[«vanlig_passord2»]? $form->getErrors(): matrise("De to passordene må være de samme"),
"form" => $form->createView(),
);
}

Her vil vi raskt detaljere arbeidsflyt for å registrere en ny bruker.

  1. Vi ser hvis alle de obligatoriske feltene er fylt inn riktig, inkludert de to "passord"-feltene, og hvis de to sistnevnte er identiske.
  2. Vi koder passordet og vi "sett" det i enheten.
  3. Ved eventuelle feil returnerer vi skjemaet med feilen som vi mener bør være detaljert.

Opprett en funksjon for å tilbakestille passordet ditt

Nå kan brukeren din logge på, men hva gjør vi hvis han mister passordet. Det er åpenbart at vi ikke kommer til å sette opp en kontakt-e-postadresse dedikert til dens ubrukelige operasjoner.

Som du har sett ovenfor, erklærer jeg vanligvis to metoder for hver av funksjonene mine: en av metodene mine er ansvarlig for å administrere visningen som er opprettet etter en forespørsel GET og et resultat av en forespørsel POST. Du kan absolutt sette disse to metodene sammen til en og samme metode.

1
2
3
4
5
6
7
8
9
/ **
  * @Metode({"FÅ"})
  * @Vei("/reset", navn = "reset")
  * @Sikre(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
  * @Mal()
  */
  offentlig funksjon tilbakestille() {
   retur matrise();
  }

I et andre trinn vil vi deklarere den komplementære metoden for å administrere forespørslene 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
/ **
* @Metode({"POST"})
* @Vei("/nullstille")
* @Sikre(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
offentlig funksjon tilbakestill nå(Be om $request)
{
$params = $request->request->all();
if (!array_key_exists("Logg Inn", $params)) {
kaste nytt Unntak("Ingen pålogging gitt");
}
$login = &$params["Logg Inn"];
$em = $ dette->beholder->få(«doctrine.orm.default_entity_manager»);
$user = $em->getRepository("NamespaceMyBundle:User")->finnEnBy(matrise("Logg Inn" => $pålogging));
if ($bruker == null) {
retur $ dette->omdirigere($ dette->genererUrl("Logg Inn", matrise()));
}
$passord = "myRandowPassword";
$user->setPassword($ dette->beholder->få(«security.encoder_factory»)->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->flush();
// Vi sender passordet på e-post
retur $ dette->omdirigere($ dette->genererUrl("Logg Inn", matrise()));
}

Denne metoden ble designet for å tilbakestiller passordet til en bruker som har oppgitt sitt pålogging/brukernavn. I mitt tilfelle ble passordet da sendt på e-post. Jeg lar deg legge til den galante linjen.

  1. Så vi går søk bruker.
  2. Vi genererer et passord at vi kommer for å informere brukeren når han har kodet i henhold til reglene som du har definert.

Sett opp passordendring

På dette tidspunktet kan brukeren vår generere et nytt passord hvis det gikk tapt, men i tilfelle han bare vil endre det, trenger vi en port for å definere en port.

1
2
3
4
5
6
7
8
9
/ **
* @Metode({"FÅ"})
* @Vei("/endre", navn = "endre passord")
* @Sikre(roller=”IS_AUTHENTICATED_FULLY”)
* @Mal()
*/
offentlig funksjon endring() {
retur matrise();
}

Her er koden for å generere visningen. Først må du skrive inn det gamle passordet ditt og deretter det nye passordet to ganger. Andre gang er konfirmasjon.

Nå skal vi se koden til tilbakestiller passordet. DE prosess ligner på å generere et nytt tilfeldig passord.

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
/ **
 * @Metode({"POST"})
 * @Vei("/endring")
 * @Sikre(roller=”IS_AUTHENTICATED_FULLY”)
 * @Mal()
 */
offentlig funksjon endre nå(Be om $request)
{
    $params = $request->request->all();
    if (!array_key_exists("nåværende", $params)
        || !array_key_exists("ny", $params)
        || !array_key_exists(«ny2», $params))
    {
        retur matrise("feil" => "Vennligst fyll ut alle feltene");
    }
    $em = $ dette->beholder->få(«doctrine.orm.default_entity_manager»);
    $bruker = $ dette->getUser();
    $user_encoders = $ dette->beholder->få(«security.encoder_factory»)->getEncoder($bruker);
    $user_repository = $em->getRepository("NamespaceMyBundle:User");
    $current_password_encoded = $user_encoders->encodePassword($params["nåværende"], $user->getSalt());
    $new_password_encoded = $user_encoders->encodePassword($params["ny"], $user->getSalt());
    if ($user_repository->finnOneBy(matrise("passord" => $current_password_encoded)) == null) {
        retur matrise("feil" => "Gjeldende passord er feil");
    } eller hvis ($params["ny"] != $params[«ny2»]) {
        retur matrise("feil" => "Passordet til de to feltene er ikke det samme");
    }
    $user->setPassword($new_password_encoded);
    $em->persist($user);
    $em->flush();
    retur $ dette->omdirigere($ dette->genererUrl("Logg ut", matrise()));
}

Hvis du bruker 1 minutt på å lese koden, vil du se at denne er spesielt enkel.

  1. Først sjekker vi om de tre feltene (gammelt passord, nytt passord og bekreftelse) er skrevet inn riktig.
  2. On skriv inn passordet nåværende og vi sammenligner det med gjeldende passordment i databasen for å se om det samsvarer med det gamle passordet som er angitt.
  3. Vi sjekker om de "to" nye passordene er det identisk.
  4. Skriv inn det nye passordet og skyv i enheten.

Aktivering av kontoen hans

Denne funksjonen er ikke detaljert perfekt i andre snutter ovenfor. Formålet er å fjerne blokkeringen av en bruker som nettopp har registrert seg, for eksempel når han har validert e-posten sin. Denne funksjonaliteten er utviklet på nesten alle plattformene vi kjenner av flere grunner. For å sette opp en blokkering av en bruker, må du kanskje også implementere en leverandør.

  • Blokkere/limit-kontoer forfalskning og spam.
  • Verifier at brukeren har fylt ut en e-postadresse som fremstår som brukbar ved første øyekast.
  • Fjerne kontoer som ikke er validert etter en viss tidsperiode.

Arbeidsflyt

  1. En bruker registrerer seg. Kontoen hans blir deretter blokkert via et felt spesifikt for deg. Dette feltet skal da hindre ham i å koble til så lenge dette feltet indikerer at kontoen er deaktivert.
1
2
3
4
5
6
7
8
// NamespaceMyBundleEntityUser
klasse Bruker {
offentlig funksjon __konstruere() {
$ dette->token = hash(«sha512», uniqid());
}
...
}
1
$user->setEnabled(falsk);
  1. Brukeren mottok en e-post når profilen hans var spyle i databasen. Denne e-posten må være en del av en adresse du genererer.
    I denne veien, en token eller unik identifikator må oppgis slik at den aktuelle brukeren kan bli funnet. Jeg anbefaler deg å bruke en UUID4 som er ment å være tilfeldig. Du kan finne listen over UUID-er samt beskrivelsen av alle versjoner.
1
2
3
4
/ **
* @Vei("/aktiver", navn = "aktiver")
*/
offentlig funksjon aktivere() {...}
1
$ dette->genererUrl("aktiver", matrise(« token » => $user->getToken()), sant);

Du bør ha en URL som denne.

1
http://vertsnavn/aktivere?token=myUniqueToken
  1. Brukeren åpner e-posten sin og prøver å aktivere kontoen sin ved å klikke på lenken som er oppgitt. Vi går deretter inn i prosessen nedenfor.
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
/ **
 * @Metode({"FÅ"})
 * @Vei("/aktiver", navn = "aktiver")
 * @Sikre(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
 * @Mal()
 */
offentlig funksjon aktivere(Be om $request) {
    $params = matrise();
    $token = $request->query->get(« token »);
    $em = $ dette->beholder->få(«doctrine.orm.default_entity_manager»);
$user = $em->getRepository("NamespaceMyBundle:User")->finnEnBy(matrise(« token » => $token));
    if ($bruker != null) {
        $user->setEnabled(sant);
        $em->persist($user);
        $em->flush();
        $params["aktiver"] = sant;
    } ellers {
        $params["aktiver"] = falsk;
    }
    retur $params;
}

Med denne prosessen skal du ikke ha noe problem med å aktivere brukerkontovalidering på plass.

Du kan finne denne tilsvarende koden på denne 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
<?php
bruke JMSSecurityExtraBundlemerknadSikre;
bruke SensioXNUMX bunkFrameworkExtraBundleKonfigurasjonMetode;
bruke SensioXNUMX bunkFrameworkExtraBundleKonfigurasjonRute;
bruke SensioXNUMX bunkFrameworkExtraBundleKonfigurasjonMal;
bruke SymfonyXNUMX bunkFrameworkBundlecontrollercontroller;
bruke SymfonyKomponentHttpFoundationBe;
bruke SymfonyKomponentSikkerhetKjerneSikkerhetskontekst;
klasse Sikkerhetskontroller strekker controller
{
/ **
* @Metode({"FÅ"})
* @Vei("/login", navn = "pålogging")
* @Mal()
*/
offentlig funksjon Logg inn(Be om $request)
{
$request= $ dette->getRequest();
$session = $request->getSession();
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} ellers {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
$params = matrise(
«last_username» => $session->get(SecurityContext::LAST_USERNAME),
"feil" => $feil,
" beskjed " => $request->get(" beskjed "),
);
if ($request->isXmlHttpRequest()) {
retur $ dette->gjengi("GCDirectoryMainBundle:Security:login-ajax.html.twig", $params);
}
retur $params;
}
/ **
* @Metode({"POST"})
* @Vei("/login_check", name="login_check")
*/
offentlig funksjon sjekk()
{
kaste nytt RuntimeException('Du må konfigurere sjekkbanen til å håndteres av brannmuren ved å bruke form_login i sikkerhetsbrannmurkonfigurasjonen.');
}
/ **
* @Metode({"FÅ"})
* @Vei("/logg ut", navn = "logg ut")
*/
offentlig funksjon utlogging()
{
kaste nytt RuntimeException('Du må aktivere utloggingen i sikkerhetsbrannmurkonfigurasjonen.');
}
/ **
* @Metode({"FÅ"})
* @Vei("/reset", navn = "reset")
* @Sikre(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Mal()
*/
offentlig funksjon tilbakestille() {
retur matrise();
}
/ **
* @Metode({"POST"})
* @Vei("/nullstille")
* @Sikre(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
offentlig funksjon tilbakestill nå(Be om $request)
{
$params = $request->request->all();
if (!array_key_exists("Logg Inn", $params)) {
kaste nytt Unntak("Ingen pålogging gitt");
}
$login = &$params["Logg Inn"];
$em = $ dette->beholder->få(«doctrine.orm.default_entity_manager»);
$user = $em->getRepository("NamespaceMyBundle:User")->finnEnBy(matrise("Logg Inn" => $pålogging));
if ($bruker == null) {
retur $ dette->omdirigere($ dette->genererUrl("Logg Inn", matrise()));
}
$passord = "myRandowPassword";
$user->setPassword($ dette->beholder->få(«security.encoder_factory»)->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->flush();
retur $ dette->omdirigere($ dette->genererUrl("Logg Inn", matrise()));
}
/ **
* @Metode({"FÅ"})
* @Vei("/endre", navn = "endre passord")
* @Sikre(roller=”IS_AUTHENTICATED_FULLY”)
* @Mal()
*/
offentlig funksjon endring() {
retur matrise();
}
/ **
* @Metode({"POST"})
* @Vei("/endring")
* @Sikre(roller=”IS_AUTHENTICATED_FULLY”)
* @Mal()
*/
offentlig funksjon endre nå(Be om $request)
{
$params = $request->request->all();
if (!array_key_exists("nåværende", $params)
|| !array_key_exists("ny", $params)
|| !array_key_exists(«ny2», $params))
{
retur matrise("feil" => "Vennligst fyll ut alle feltene");
}
$em = $ dette->beholder->få(«doctrine.orm.default_entity_manager»);
$bruker = $ dette->getUser();
$user_encoders = $ dette->beholder->få(«security.encoder_factory»)->getEncoder($bruker);
$user_repository = $em->getRepository("NamespaceMyBundle:User");
$current_password_encoded = $user_encoders->encodePassword($params["nåværende"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["ny"], $user->getSalt());
if ($user_repository->finnOneBy(matrise("passord" => $current_password_encoded)) == null) {
retur matrise("feil" => "Gjeldende passord er feil");
} eller hvis ($params["ny"] != $params[«ny2»]) {
retur matrise("feil" => "Passordet til de to feltene er ikke det samme");
}
$user->setPassword($new_password_encoded);
$em->persist($user);
$em->flush();
retur $ dette->omdirigere($ dette->genererUrl("Logg ut", matrise()));
}
/ **
* @Metode({"FÅ"})
* @Vei("/register", navn="register")
* @Sikre(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Mal()
*/
offentlig funksjon registrere()
{
$form = $ dette->opprett skjema(nytt UserType(UserType::REGISTER), nytt Bruker());
retur matrise(
"form" => $form->createView(),
);
}
/ **
* @Metode({"POST"})
* @Vei("/registrere")
* @Sikre(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Mal()
*/
offentlig funksjon Registrer deg nå(Be om $request)
{
$params = $request->request->all()[«navn_på_min_skjema»];
$form = $ dette->opprett skjema(nytt UserType(UserType::REGISTER), nytt Bruker());
$form->submit($request);
if (array_key_exists(«vanlig_passord», $params) && array_key_exists(«vanlig_passord2», $params) && $params[«vanlig_passord»] == $params[«vanlig_passord2»]) {
if ($form->isValid()) {
$data = $form->getData();
$data->setPassword($ dette->beholder->få(«security.encoder_factory»)->getEncoder($data)->encodePassword($params[«vanlig_passord»], $data->getSalt()));
$em->persist($data);
$em->flush();
retur $ dette->omdirigere($ dette->genererUrl("Logg Inn", matrise(" beskjed " => "Du har mottatt en e-post for å bekrefte kontoen din. »)));
}
}
retur matrise(
"feil" => $params[«vanlig_passord»] == $params[«vanlig_passord2»]? $form->getErrors(): matrise("De to passordene må være de samme"),
"form" => $form->createView(),
);
}
/ **
* @Metode({"FÅ"})
* @Vei("/aktiver", navn = "aktiver")
* @Sikre(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Mal()
*/
offentlig funksjon aktivere(Be om $request) {
$params = matrise();
$token = $request->query->get(« token »);
$em = $ dette->beholder->få(«doctrine.orm.default_entity_manager»);
$user = $em->getRepository("NamespaceMyBundle:User")->finnEnBy(matrise(« token » => $token));
if ($bruker != null) {
$user->setActive(Bruker::ACTIVE_ACTIVE);
$em->persist($user);
$em->flush();
$params["aktiver"] = sant;
} ellers {
$params["aktiver"] = falsk;
}
retur $params;
}
}

★ ★ ★ ★ ★