Implementieren Sie Ihren eigenen SecurityController
Webagentur » Digitale Nachrichten » Implementieren Sie Ihren eigenen SecurityController

Implementieren Sie Ihren eigenen SecurityController

Ich habe kürzlich einen Artikel für mein Unternehmen über die Verwaltung von Benutzern und deren Authentifizierung geschrieben, die nativ mit dem Symfony2 Core und daher ohne FOSUserBundle verwendet wird. Nach diesem bereits reichhaltigen ersten Artikel wollte ich einen zweiten, ebenso nützlichen Teil beschreiben, der es uns ermöglicht, die wesentlichen Funktionen schnell einzurichten, nämlich das Zurücksetzen Ihres Passworts, das Ändern Ihres Passworts, die Validierung Ihres Kontos oder sogar die Registrierung. Aktionen sind ebenso wichtig, wenn Sie ein System haben, das Benutzer verwaltet.

Richten Sie einen SecurityController ein

Erstens, wenn Sie das erste Tutorial zur Einrichtung der Benutzerverwaltung nicht befolgt haben, empfehle ich Ihnen, einen Blick darauf zu werfen. Wenn Sie der Lösung gefolgt sind, sollten Sie logischerweise einen SecurityController oder etwas anderes haben. In meinem Fall habe ich nur drei Methoden, von denen nur eine wirklich brauchbar ist.

  1. LoginAktion
    Diese Methode verbindet einen Benutzer.
  2. checkAktion
    Mit dieser Methode können Sie einfach eine Route für die Firewall deklarieren, die es einem Benutzer ermöglicht, sich auf der Serverseite zu verbinden.
  3. Abmeldeaktion
    Diese Methode wird verwendet, um eine Route für die Firewall zu deklarieren, die es einem Benutzer ermöglicht, die Verbindung zu trennen.

Öffnen Sie unsere Plattform für neue Benutzer

Besonders interessant wäre es, wenn sich unsere Nutzer verbinden und sich somit vorher registrieren könnten.

Zuerst generieren wir das Formular mit den Informationen, die Sie Ihren Benutzer fragen möchten.

In Bezug auf das Formular, das Sie verwenden, um Ihren Benutzer zu registrieren, wissen, dass das Feld " Passwort sollte nicht in Ihrer Form sein. Sie müssen jedoch zwei Felder hinzufügen " nicht abgebildet um das gewünschte Passwort zweimal eingeben zu lassen.

1
2
3
4
5
6
7
8
9
10
11
12
13
/ **
 * @Methode({"ERHALTEN"})
 * @Straße(„/registrieren“, name=“registrieren“)
 * @Sicher(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
 * @Vorlage()
 */
Öffentlichkeit Funktion Registrieren()
{
    $form = $ This->Formular erstellen(neu Benutzertyp(Benutzertyp::REGISTER), neu Benutzer());
    Rückkehr Array(
        "form" => $form->createView(),
        );
}

Wenn Ihr Benutzer dann mit ausgefülltem Formular zurückkommt, müssen wir ihn registrieren oder seine Datei ablehnen :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
/ **
* @Methode({"POST"})
* @Straße("/registrieren")
* @Sicher(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Vorlage()
*/
Öffentlichkeit Funktion jetzt registrieren(Anfrage $request)
{
$params = $request->request->all()[„Name_meines_Formulars“];
$form = $ This->Formular erstellen(neu Benutzertyp(Benutzertyp::REGISTER), neu Benutzer());
$form->submit($request);
if (array_key_exists(„einfaches_Passwort“, $params) && array_key_exists(„einfaches_passwort2“, $params) && $params[„einfaches_Passwort“] == $params[„einfaches_passwort2“]) {
if ($form->isValid()) {
$data = $form->getData();
$data->setPassword($ This->Behälter->holen(„security.encoder_factory“)->getEncoder($data)->encodePassword($params[„einfaches_Passwort“], $data->getSalt()));
$em->persist($data);
$em->flush();
Rückkehr $ This->weiterleiten($ This->Url generieren("Anmeldung", Array(" Botschaft " => „Sie haben eine E-Mail zur Bestätigung Ihres Kontos erhalten. »)));
}
}
Rückkehr Array(
„Fehler“ => $params[„einfaches_Passwort“] == $params[„einfaches_passwort2“]? $form->getErrors(): Array(„Die beiden Passwörter müssen gleich sein“),
"form" => $form->createView(),
);
}

Hier werden wir schnell detailliert die Arbeitsablauf. um einen neuen Benutzer zu registrieren.

  1. Wir schauen wenn alle Pflichtfelder korrekt ausgefüllt sind, einschließlich der beiden "Passwort"-Felder, und wenn die beiden letzteren identisch sind.
  2. Wir verschlüsseln das Passwort und wir „setzen“ es in der Entität.
  3. Im Falle eines Fehlers senden wir das Formular mit dem Fehler zurück, der unserer Meinung nach detailliert werden sollte.

Erstellen Sie eine Funktion zum Zurücksetzen Ihres Passworts

Jetzt kann sich Ihr Benutzer anmelden, aber was tun wir, wenn er sein Passwort verliert? Es ist offensichtlich, dass wir keine Kontakt-E-Mail-Adresse einrichten werden, die für seine nutzlosen Operationen bestimmt ist.

Wie Sie oben gesehen haben, deklariere ich normalerweise zwei Methoden für jedes meiner Features: Eine meiner Methoden ist für die Verwaltung der Ansicht verantwortlich, die nach einer Anfrage erstellt wird BESTELLE und ein Ergebnis einer Anfrage jetzt lesen. Sie können diese beiden Methoden durchaus zu ein und derselben Methode verketten.

1
2
3
4
5
6
7
8
9
/ **
  * @Methode({"ERHALTEN"})
  * @Straße(„/reset“, name=“reset“)
  * @Sicher(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
  * @Vorlage()
  */
  Öffentlichkeit Funktion zurückstellen() {
   Rückkehr Array();
  }

In einem zweiten Schritt deklarieren wir die ergänzende Methode zur Verwaltung der Anfragen jetzt lesen.

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
/ **
* @Methode({"POST"})
* @Straße("/zurücksetzen")
* @Sicher(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
Öffentlichkeit Funktion Jetzt zurücksetzen(Anfrage $request)
{
$params = $request->request->all();
if (!array_key_exists("Anmeldung", $params)) {
werfen neu Exception(„Kein Login angegeben“);
}
$login = &$params["Anmeldung"];
$em = $ This->Behälter->holen(„doctrine.orm.default_entity_manager“);
$user = $em->getRepository(„NamespaceMyBundle:Benutzer“)->findOneBy(Array("Anmeldung" => $login));
if ($user == null) {
Rückkehr $ This->weiterleiten($ This->Url generieren("Anmeldung", Array()));
}
$Passwort = „myRandowPasswort“;
$user->setPassword($ This->Behälter->holen(„security.encoder_factory“)->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->flush();
// Wir senden das Passwort per E-Mail
Rückkehr $ This->weiterleiten($ This->Url generieren("Anmeldung", Array()));
}

Diese Methode wurde entwickelt, um zurücksetzen das Passwort eines Benutzers, der seins angegeben hat Login Benutzername. In meinem Fall wurde das Passwort dann per E-Mail zugesendet. Ich lasse Sie diesen galanten Satz hinzufügen.

  1. Also gehen wir Benutzer suchen.
  2. Wir generieren ein Passwort dass wir den Benutzer informieren, sobald er gemäß den von Ihnen definierten Regeln codiert hat.

Passwortänderung einrichten

An dieser Stelle kann unser Benutzer ein neues Passwort generieren, wenn es verloren gegangen ist, aber falls er es nur ändern möchte, benötigen wir ein Tor, um ein Tor zu definieren.

1
2
3
4
5
6
7
8
9
/ **
* @Methode({"ERHALTEN"})
* @Straße(„/ändern“, name=“passwort ändern“)
* @Sicher(roles=”IS_AUTHENTICATED_FULLY”)
* @Vorlage()
*/
Öffentlichkeit Funktion Übernehmen () {
Rückkehr Array();
}

Hier ist der Code zum Generieren der Ansicht. Zuerst müssen Sie Ihr altes Passwort eingeben und dann zweimal Ihr neues Passwort. Das zweite Mal ist Konfirmation.

Jetzt sehen wir uns den Code an Resetter das Passwort. DER Prozessdefinierung ähnelt dem Generieren eines neuen zufälligen Passworts.

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
/ **
 * @Methode({"POST"})
 * @Straße("/ändern")
 * @Sicher(roles=”IS_AUTHENTICATED_FULLY”)
 * @Vorlage()
 */
Öffentlichkeit Funktion jetzt ändern(Anfrage $request)
{
    $params = $request->request->all();
    if (!array_key_exists("aktuell", $parameter)
        || !array_key_exists("neu", $parameter)
        || !array_key_exists(„neu2“, $params))
    {
        Rückkehr Array("Fehler" => "Bitte alle Felder ausfüllen");
    }
    $em = $ This->Behälter->holen(„doctrine.orm.default_entity_manager“);
    $user= $ This->getUser();
    $user_encoders = $ This->Behälter->holen(„security.encoder_factory“)->getEncoder($user);
    $user_repository = $em->getRepository(„NamespaceMyBundle:Benutzer“);
    $current_password_encoded = $user_encoders->encodePassword($params["aktuell"], $user->getSalt());
    $new_password_encoded = $user_encoders->encodePassword($params["neu"], $user->getSalt());
    if ($user_repository->findOneBy(Array("Passwort" => $aktuelles_passwort_verschlüsselt)) == null) {
        Rückkehr Array("Fehler" => „Das aktuelle Passwort ist falsch“);
    } elseif ($params["neu"] != $params[„neu2“]) {
        Rückkehr Array("Fehler" => "Die beiden Felder Passwort sind nicht gleich");
    }
    $user->setPassword($new_password_encoded);
    $em->persist($user);
    $em->flush();
    Rückkehr $ This->weiterleiten($ This->Url generieren("Ausloggen", Array()));
}

Wenn Sie sich 1 Minute Zeit nehmen, um den Code zu lesen, werden Sie sehen, dass dieser besonders einfach ist.

  1. Zunächst prüfen wir, ob die drei Felder (altes Passwort, neues Passwort und Bestätigung) korrekt ausgefüllt wurden.
  2. On Geben Sie das Passwort ein aktuell u wir vergleichen es mit dem aktuellen Passwortin der Datenbank nachsehen, ob es mit dem alten eingegebenen Passwort übereinstimmt.
  3. Wir prüfen, ob die "zwei" neuen Passwörter sind identiques.
  4. Geben Sie das neue Passwort ein und drücken in der Entität.

Aktivierung seines Kontos

Diese Funktion ist in anderen nicht perfekt beschrieben Snippets über. Sein Zweck besteht darin, einen Benutzer zu entsperren, der sich gerade registriert hat, wenn er beispielsweise seine E-Mail-Adresse validiert hat. Diese Funktionalität wird aus mehreren Gründen auf fast allen uns bekannten Plattformen entwickelt. Um eine Sperrung eines Benutzers einzurichten, müssen Sie möglicherweise auch einen Anbieter implementieren.

  • Block/limit Konten Fälschung und Spam.
  • überprüfen dass der Nutzer eine auf den ersten Blick brauchbare E-Mail-Adresse eingetragen hat.
  • Entfernen Konten, die nach einer bestimmten Zeit nicht validiert wurden.

Arbeitsablauf

  1. Ein Benutzer registriert sich. Sein Konto wird dann über ein für Sie spezifisches Feld gesperrt. Dieses Feld sollte ihn dann daran hindern, sich zu verbinden, solange dieses Feld anzeigt, dass das Konto deaktiviert ist.
1
2
3
4
5
6
7
8
// NamespaceMyBundleEntityUser
Klasse Mitglied {
Öffentlichkeit Funktion __bauen() {
$ This->token = Hash(„sha512“, uniqid());
}
...
}
1
$user->setEnabled(falsch);
  1. Der Benutzer erhielt eine E-Mail, wenn sein Profil war Spüler in Datenbank. Diese E-Mail muss Teil einer von Ihnen generierten Adresse sein.
    In dieser Straße, a token oder es muss eine eindeutige Kennung angegeben werden, die es ermöglicht, den betreffenden Benutzer zu finden. Ich rate Ihnen, eine UUID4 zu verwenden, die zufällig sein soll. Sie finden die Liste der UUIDs sowie die Beschreibung aller Versionen.
1
2
3
4
/ **
* @Straße(„/aktivieren“, name=“aktivieren“)
*/
Öffentlichkeit Funktion aktivieren() {...}
1
$ This->Url generieren("aktivieren Sie", Array(« token » => $user->getToken()), was immer dies auch sein sollte.);

Sie sollten eine URL wie diese haben.

1
http://hostname/aktivieren?token=myUniqueToken
  1. Der Benutzer öffnet seine E-Mail und versucht, sein Konto zu aktivieren, indem er auf den bereitgestellten Link klickt. Wir treten dann in den folgenden Prozess ein.
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
/ **
 * @Methode({"ERHALTEN"})
 * @Straße(„/aktivieren“, name=“aktivieren“)
 * @Sicher(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
 * @Vorlage()
 */
Öffentlichkeit Funktion aktivieren(Anfrage $request) {
    $params = Array();
    $token = $request->query->get(« token »);
    $em = $ This->Behälter->holen(„doctrine.orm.default_entity_manager“);
$user = $em->getRepository(„NamespaceMyBundle:Benutzer“)->findOneBy(Array(« token » => $token));
    if ($user != null) {
        $user->setEnabled(was immer dies auch sein sollte.);
        $em->persist($user);
        $em->flush();
        $params["aktivieren Sie"] = was immer dies auch sein sollte.;
    } sonst {
        $params["aktivieren Sie"] = falsch;
    }
    Rückkehr $params;
}

Mit diesem Prozess sollten Sie kein Problem haben, die Validierung des Benutzerkontos zu aktivieren.

Sie finden diesen äquivalenten Code in diesem 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
- JMSSecurityExtraBundleAnmerkungSicher;
- SensiobündelnFrameworkExtraBundleKonfigurationVersandart;
- SensiobündelnFrameworkExtraBundleKonfigurationStraße;
- SensiobündelnFrameworkExtraBundleKonfigurationTemplate;
- SymfoniebündelnFrameworkBundleControllerController;
- SymfonieKomponenteHttpFoundationPREISANFRAGE (Request);
- SymfonieKomponenteSicherheitKernbereichSicherheitskontext;
Klasse Sicherheitscontroller erweitert Controller
{
/ **
* @Methode({"ERHALTEN"})
* @Straße(„/login“, name=“login“)
* @Vorlage()
*/
Öffentlichkeit Funktion login(Anfrage $request)
{
$anfrage = $ This->getRequest();
$session = $request->getSession();
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} sonst {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
$params = Array(
„last_username“ => $session->get(SecurityContext::LAST_USERNAME),
"Fehler" => $Fehler,
" Botschaft " => $request->get(" Botschaft "),
);
if ($request->isXmlHttpRequest()) {
Rückkehr $ This-> rendern („GCDirectoryMainBundle:Sicherheit:login-ajax.html.twig“, $parameter);
}
Rückkehr $params;
}
/ **
* @Methode({"POST"})
* @Straße(„/login_check“, name=“login_check“)
*/
Öffentlichkeit Funktion aus der Ferne überprüfen()
{
werfen neu RuntimeException ('Sie müssen den Prüfpfad konfigurieren, der von der Firewall gehandhabt werden soll, indem Sie form_login in Ihrer Sicherheits-Firewall-Konfiguration verwenden.');
}
/ **
* @Methode({"ERHALTEN"})
* @Straße(„/logout“, name=“logout“)
*/
Öffentlichkeit Funktion Abmeldung()
{
werfen neu RuntimeException ('Sie müssen die Abmeldung in Ihrer Sicherheits-Firewall-Konfiguration aktivieren.');
}
/ **
* @Methode({"ERHALTEN"})
* @Straße(„/reset“, name=“reset“)
* @Sicher(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Vorlage()
*/
Öffentlichkeit Funktion zurückstellen() {
Rückkehr Array();
}
/ **
* @Methode({"POST"})
* @Straße("/zurücksetzen")
* @Sicher(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
Öffentlichkeit Funktion Jetzt zurücksetzen(Anfrage $request)
{
$params = $request->request->all();
if (!array_key_exists("Anmeldung", $params)) {
werfen neu Exception(„Kein Login angegeben“);
}
$login = &$params["Anmeldung"];
$em = $ This->Behälter->holen(„doctrine.orm.default_entity_manager“);
$user = $em->getRepository(„NamespaceMyBundle:Benutzer“)->findOneBy(Array("Anmeldung" => $login));
if ($user == null) {
Rückkehr $ This->weiterleiten($ This->Url generieren("Anmeldung", Array()));
}
$Passwort = „myRandowPasswort“;
$user->setPassword($ This->Behälter->holen(„security.encoder_factory“)->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->flush();
Rückkehr $ This->weiterleiten($ This->Url generieren("Anmeldung", Array()));
}
/ **
* @Methode({"ERHALTEN"})
* @Straße(„/ändern“, name=“passwort ändern“)
* @Sicher(roles=”IS_AUTHENTICATED_FULLY”)
* @Vorlage()
*/
Öffentlichkeit Funktion Übernehmen () {
Rückkehr Array();
}
/ **
* @Methode({"POST"})
* @Straße("/ändern")
* @Sicher(roles=”IS_AUTHENTICATED_FULLY”)
* @Vorlage()
*/
Öffentlichkeit Funktion jetzt ändern(Anfrage $request)
{
$params = $request->request->all();
if (!array_key_exists("aktuell", $parameter)
|| !array_key_exists("neu", $parameter)
|| !array_key_exists(„neu2“, $params))
{
Rückkehr Array("Fehler" => "Bitte alle Felder ausfüllen");
}
$em = $ This->Behälter->holen(„doctrine.orm.default_entity_manager“);
$user= $ This->getUser();
$user_encoders = $ This->Behälter->holen(„security.encoder_factory“)->getEncoder($user);
$user_repository = $em->getRepository(„NamespaceMyBundle:Benutzer“);
$current_password_encoded = $user_encoders->encodePassword($params["aktuell"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["neu"], $user->getSalt());
if ($user_repository->findOneBy(Array("Passwort" => $aktuelles_passwort_verschlüsselt)) == null) {
Rückkehr Array("Fehler" => „Das aktuelle Passwort ist falsch“);
} elseif ($params["neu"] != $params[„neu2“]) {
Rückkehr Array("Fehler" => "Die beiden Felder Passwort sind nicht gleich");
}
$user->setPassword($new_password_encoded);
$em->persist($user);
$em->flush();
Rückkehr $ This->weiterleiten($ This->Url generieren("Ausloggen", Array()));
}
/ **
* @Methode({"ERHALTEN"})
* @Straße(„/registrieren“, name=“registrieren“)
* @Sicher(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Vorlage()
*/
Öffentlichkeit Funktion Registrieren()
{
$form = $ This->Formular erstellen(neu Benutzertyp(Benutzertyp::REGISTER), neu Benutzer());
Rückkehr Array(
"form" => $form->createView(),
);
}
/ **
* @Methode({"POST"})
* @Straße("/registrieren")
* @Sicher(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Vorlage()
*/
Öffentlichkeit Funktion jetzt registrieren(Anfrage $request)
{
$params = $request->request->all()[„Name_meines_Formulars“];
$form = $ This->Formular erstellen(neu Benutzertyp(Benutzertyp::REGISTER), neu Benutzer());
$form->submit($request);
if (array_key_exists(„einfaches_Passwort“, $params) && array_key_exists(„einfaches_passwort2“, $params) && $params[„einfaches_Passwort“] == $params[„einfaches_passwort2“]) {
if ($form->isValid()) {
$data = $form->getData();
$data->setPassword($ This->Behälter->holen(„security.encoder_factory“)->getEncoder($data)->encodePassword($params[„einfaches_Passwort“], $data->getSalt()));
$em->persist($data);
$em->flush();
Rückkehr $ This->weiterleiten($ This->Url generieren("Anmeldung", Array(" Botschaft " => „Sie haben eine E-Mail zur Bestätigung Ihres Kontos erhalten. »)));
}
}
Rückkehr Array(
„Fehler“ => $params[„einfaches_Passwort“] == $params[„einfaches_passwort2“]? $form->getErrors(): Array(„Die beiden Passwörter müssen gleich sein“),
"form" => $form->createView(),
);
}
/ **
* @Methode({"ERHALTEN"})
* @Straße(„/aktivieren“, name=“aktivieren“)
* @Sicher(roles=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Vorlage()
*/
Öffentlichkeit Funktion aktivieren(Anfrage $request) {
$params = Array();
$token = $request->query->get(« token »);
$em = $ This->Behälter->holen(„doctrine.orm.default_entity_manager“);
$user = $em->getRepository(„NamespaceMyBundle:Benutzer“)->findOneBy(Array(« token » => $token));
if ($user != null) {
$user->setActive(Benutzer::ACTIVE_ACTIVE);
$em->persist($user);
$em->flush();
$params["aktivieren Sie"] = was immer dies auch sein sollte.;
} sonst {
$params["aktivieren Sie"] = falsch;
}
Rückkehr $params;
}
}

★ ★ ★ ★ ★