Kendi SecurityController'ınızı uygulayın
Web ajansı » Dijital haberler » Kendi SecurityController'ınızı uygulayın

Kendi SecurityController'ınızı uygulayın

Geçenlerde şirketim için Symfony2 Core'u yerel olarak ve dolayısıyla FOSUserBundle olmadan kullanarak kullanıcıları ve kimlik doğrulamalarını yönetme hakkında bir makale yazdım. Zaten zengin olan bu ilk makalenin ardından, parolanızı sıfırlama, parolanızı değiştirme, hesabınızı doğrulama ve hatta kayıt olma gibi temel işlevleri hızlı bir şekilde kurmamıza izin verecek eşit derecede yararlı ikinci bir bölümü açıklamak istedim. Kullanıcıları yöneten bir sisteminiz olduğunda eylemler de aynı derecede önemlidir.

Bir SecurityController kurun

İlk olarak, kullanıcı yönetiminin nasıl kurulacağına ilişkin ilk öğreticiyi izlemediyseniz, bir göz atmanızı tavsiye ederim. Çözümü izlediyseniz, mantıksal olarak bir SecurityController'a veya başka bir şeye sahip olmalısınız. Benim durumumda, sadece biri gerçekten kullanılabilir olan sadece üç yöntemim var.

  1. loginAksiyon
    Bu yöntem bir kullanıcıyı bağlar.
  2. checkAksiyon
    Bu yöntem, bir kullanıcının sunucu tarafında bağlanmasına izin vererek, güvenlik duvarı için bir yol bildirmenize izin verir.
  3. çıkışAksiyon
    Bu yöntem, güvenlik duvarı için bir kullanıcının bağlantısının kesilmesine izin veren bir rota bildirmek için kullanılır.

Platformumuzu yeni kullanıcılara açın

Kullanıcılarımızın bağlantı kurabilmeleri ve bu nedenle önceden kayıt olabilmeleri özellikle ilginç olurdu.

Öncelikle, kullanıcınıza sormak istediğiniz bilgileri içeren formu oluşturuyoruz.

Kullanıcınızı kaydetmek için kullanacağınız formla ilgili olarak, alanın olduğunu bilin" şifre formunda olmamalıdır. Ancak, iki alan eklemeniz gerekecek " eşlenmemiş İstenen şifrenin iki kez girilmesi için.

1
2
3
4
5
6
7
8
9
10
11
12
13
/ **
 * @Yöntem({"ELDE ETMEK"})
 * @Yol(“/kayıt”, ad=”kayıt”)
 * @Güvenli(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
 * @Şablon()
 */
halka açık işlev kayıt olmak()
{
    $biçim = bu $->Form oluştur(yeni KullanıcıTürü(KullanıcıTürü::KAYIT), yeni Kullanıcı());
    dönüş dizi(
        "biçim" => $form->createView(),
        );
}

Ardından, kullanıcınız formu doldurulmuş olarak geri geldiğinde, onu kaydetmemiz veya dosyasını reddetmemiz gerekecek :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
/ **
* @Yöntem({"POSTALAMAK"})
* @Yol("/kayıt olmak")
* @Güvenli(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Şablon()
*/
halka açık işlev şimdi üye Ol(İstek $istek)
{
$params = $request->request->all()["formumun_adı"];
$biçim = bu $->Form oluştur(yeni KullanıcıTürü(KullanıcıTürü::KAYIT), yeni Kullanıcı());
$form->gönder($istek);
if (dizi_anahtar_var(“düz_şifre”, $paramlar) && array_key_exists("düz_şifre2", $paramlar) && $paramlar[“düz_şifre”] == $paramlar["düz_şifre2"]) {
if ($form->isValid()) {
$data = $form->getData();
$data->setPassword(bu $->konteyner->al("security.encoder_factory")->getEncoder($data)->encodePassword($params[“düz_şifre”], $data->getSalt()));
$em->persist($veri);
$em->flush();
dönüş bu $-> yönlendirme (bu $->oluşturUrl("giriş yapmak", dizi(" İleti " => "Hesabınızı doğrulamak için bir e-posta aldınız. »));
}
}
dönüş dizi(
"hatalar" => $paramlar[“düz_şifre”] == $paramlar["düz_şifre2"]? $form->getErrors(): dizi(“İki şifre aynı olmalı”),
"biçim" => $form->createView(),
);
}

Burada hızlı bir şekilde detaylandıracağız iş akışı Yeni bir kullanıcı kaydetmek için.

  1. bakıyoruz gerekli tüm alanlar doğru girildiyse, iki "şifre" alanı dahil ve son ikisi aynıysa.
  2. Şifreyi kodluyoruz ve biz onu varlıkta "ayarlıyoruz".
  3. Herhangi bir hata durumunda, detaylandırılması gerektiğini düşündüğümüz hata ile formu döndürürüz.

Parolanızı sıfırlamak için bir özellik oluşturun

Artık kullanıcınız giriş yapabilir ancak şifresini kaybederse ne yapacağız? İşe yaramaz işlemlerine adanmış bir iletişim e-posta adresi oluşturmayacağımız açıktır.

Yukarıda gördüğünüz gibi, özelliklerimin her biri için genellikle iki yöntem bildiririm: Yöntemlerimden biri, bir isteğin ardından oluşturulan görünümü yönetmekten sorumludur. GET ve bir isteğin sonucu POST. Bu iki yöntemi kesinlikle tek ve aynı yöntemde birleştirebilirsiniz.

1
2
3
4
5
6
7
8
9
/ **
  * @Yöntem({"ELDE ETMEK"})
  * @Yol(“/reset”, ad=”reset”)
  * @Güvenli(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
  * @Şablon()
  */
  halka açık işlev ayarlamak() {
   dönüş dizi();
  }

İkinci adımda, istekleri yöneten tamamlayıcı yöntemi açıklayacağız. 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
/ **
* @Yöntem({"POSTALAMAK"})
* @Yol("/Sıfırla")
* @Güvenli(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
halka açık işlev şimdi sıfırla(İstek $istek)
{
$params = $request->request->all();
if (!array_key_exists("giriş yapmak", $paramlar)) {
atmak yeni Istisna(“Giriş yapılmadı”);
}
$giriş = &$paramlar["giriş yapmak"];
$ em = bu $->konteyner->al("doctrine.orm.default_entity_manager");
$user = $em->getRepository("NamespaceMyBundle:Kullanıcı")->bulBirBy(dizi("giriş yapmak" => $giriş));
if ($kullanıcı == boş) {
dönüş bu $-> yönlendirme (bu $->oluşturUrl("giriş yapmak", dizi());
}
$şifre = “RandowParolam”;
$user->setPassword(bu $->konteyner->al("security.encoder_factory")->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->flush();
// Şifreyi e-posta ile gönderiyoruz
dönüş bu $-> yönlendirme (bu $->oluşturUrl("giriş yapmak", dizi());
}

Bu yöntem, resetter sağlayan bir kullanıcının şifresi Kullanıcı adını gir. Benim durumumda, şifre daha sonra e-posta ile gönderildi. O cesur dizeyi eklemenize izin vereceğim.

  1. yani gidiyoruz kullanıcı ara.
  2. bir şifre oluşturuyoruz tanımladığınız kurallara göre kodladıktan sonra kullanıcıya haber vermeye geldik.

Şifre değişikliğini ayarla

Bu noktada, kullanıcımız şifresini kaybederse yeni bir şifre oluşturabilir, ancak sadece değiştirmek istiyorsa, bir kapı tanımlamak için bir kapıya ihtiyacımız vardır.

1
2
3
4
5
6
7
8
9
/ **
* @Yöntem({"ELDE ETMEK"})
* @Yol(“/change”, name=”password-değiştir”)
* @Güvenli(roller=”IS_AUTHENTICATED_FULLY”)
* @Şablon()
*/
halka açık işlev değişiklik() {
dönüş dizi();
}

İşte görünümü oluşturmak için kod. İlk önce eski şifrenizi girmeniz, ardından yeni şifrenizi iki kez girmeniz gerekecektir. İkinci kez onaylanıyor.

Şimdi kodu göreceğiz sıfırlayıcı şifre. ONLAR süreç yeni bir rasgele parola oluşturmaya benzer.

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
/ **
 * @Yöntem({"POSTALAMAK"})
 * @Yol("/değiştirmek")
 * @Güvenli(roller=”IS_AUTHENTICATED_FULLY”)
 * @Şablon()
 */
halka açık işlev şimdi değiştir(İstek $istek)
{
    $params = $request->request->all();
    if (!array_key_exists("akım", $paramlar)
        || !array_key_exists("yeni", $paramlar)
        || !array_key_exists(“yeni2”, $paramlar))
    {
        dönüş dizi("hata" => "Lütfen tüm alanları doldurun");
    }
    $ em = bu $->konteyner->al("doctrine.orm.default_entity_manager");
    $kullanıcı = bu $->getUser();
    $user_enkoderler = bu $->konteyner->al("security.encoder_factory")->getEncoder($user);
    $user_repository = $em->getRepository("NamespaceMyBundle:Kullanıcı");
    $current_password_encoded = $user_encoders->encodePassword($params["akım"], $user->getSalt());
    $new_password_encoded = $user_encoders->encodePassword($params["yeni"], $user->getSalt());
    if ($user_repository->findOneBy(dizi("şifre" => $current_password_encoded)) == boş) {
        dönüş dizi("hata" => “Geçerli şifre yanlış”);
    } elseif ($paramlar["yeni"] != $paramlar[“yeni2”]) {
        dönüş dizi("hata" => "İki alan şifresi aynı değil");
    }
    $user->setPassword($new_password_encoded);
    $em->persist($user);
    $em->flush();
    dönüş bu $-> yönlendirme (bu $->oluşturUrl("çıkış Yap", dizi());
}

Kodu okumak için 1 dakikanızı ayırırsanız, bunun özellikle basit olduğunu göreceksiniz.

  1. Öncelikle üç alanın (eski şifre, yeni şifre ve onay) doğru girilip girilmediğini kontrol ediyoruz.
  2. On şifreyi gir akım ve mevcut şifre ile karşılaştırıyoruzgirilen eski şifre ile uyuşup uyuşmadığına bakılır.
  3. "İki" yeni şifrenin olup olmadığını kontrol ediyoruz özdeş.
  4. Yeni şifreyi girin ve itmek varlıkta.

Hesabının etkinleştirilmesi

Bu özellik diğerlerinde mükemmel bir şekilde detaylandırılmamıştır. parçacıkları üstünde. Amacı, örneğin e-postasını doğruladığında, yeni kaydolan bir kullanıcının engellemesini kaldırmaktır. Bu işlevsellik, birkaç nedenden dolayı bildiğimiz hemen hemen tüm platformlarda geliştirilmiştir. Bir kullanıcının engellenmesini ayarlamak için bir sağlayıcı uygulamanız da gerekebilir.

  • Blok/hesapları sınırla sahte ve Spam.
  • Verifier kullanıcının ilk bakışta kullanılabilir görünen bir e-posta adresini doldurmuş olması.
  • Kaldırmak Belli bir süre sonra onaylanmayan hesaplar.

İş Akışı

  1. Bir kullanıcı kaydolur. Daha sonra size özel bir alan aracılığıyla hesabı bloke edilir. Bu alan, hesabın devre dışı bırakıldığını gösterdiği sürece bu alanın bağlanmasını önlemelidir.
1
2
3
4
5
6
7
8
// NamespaceMyBundleEntityUser
sınıf kullanıcı {
halka açık işlev __yapı() {
bu $->token = karma(“sha512”, uniqid());
}
...
}
1
$user->setEnabled(yanlış);
  1. Kullanıcı, profili açıkken bir e-posta aldı. floş veritabanında. Bu e-posta, oluşturduğunuz bir adresin parçası olmalıdır.
    Bu yolda bir token veya ilgili kullanıcının bulunmasına izin veren benzersiz tanımlayıcı verilmelidir. Rastgele olması amaçlanan bir UUID4 kullanmanızı tavsiye ederim. UUID'lerin listesini ve tüm sürümlerin açıklamasını bulabilirsiniz.
1
2
3
4
/ **
* @Yol(“/etkinleştir”, ad=”etkinleştir”)
*/
halka açık işlev aktive() {…}
1
bu $->oluşturUrl("etkinleştir", dizi(« token » => $kullanıcı->alToken()) gerçek);

Bunun gibi bir URL'niz olmalıdır.

1
http://ana bilgisayar adı/etkinleştirilsin mi?token=benzersizimToken
  1. Kullanıcı e-postasını açar ve sağlanan bağlantıya tıklayarak hesabını etkinleştirmeye çalışır. Ardından aşağıdaki işleme giriyoruz.
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
/ **
 * @Yöntem({"ELDE ETMEK"})
 * @Yol(“/etkinleştir”, ad=”etkinleştir”)
 * @Güvenli(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
 * @Şablon()
 */
halka açık işlev aktive(İstek $istek) {
    $param = dizi();
    $token = $istek->sorgu->getir(« token »);
    $ em = bu $->konteyner->al("doctrine.orm.default_entity_manager");
$user = $em->getRepository("NamespaceMyBundle:Kullanıcı")->bulBirBy(dizi(« token » => $token));
    if ($kullanıcı != boş) {
        $user->setEnabled(gerçek);
        $em->persist($user);
        $em->flush();
        $param["etkinleştir"] = gerçek;
    } başka {
        $param["etkinleştir"] = yanlış;
    }
    dönüş $param;
}

Bu işlemle, yerinde kullanıcı hesabı doğrulamasını etkinleştirirken sorun yaşamazsınız.

Bu eşdeğer kodu bu Gist'te bulabilirsiniz.

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
kullanım JMSGüvenlikEkstraBundlenotGüvenli;
kullanım sensiodemetÇerçeveEkstraBundleyapılandırmaYöntem;
kullanım sensiodemetÇerçeveEkstraBundleyapılandırmaRota;
kullanım sensiodemetÇerçeveEkstraBundleyapılandırmaşablon;
kullanım Symfony'nindemetÇerçeveBundlekontrolörkontrolör;
kullanım Symfony'ninBileşenHttpVakfıTalep et;
kullanım Symfony'ninBileşenGüvenlikçekirdekGüvenlikBağlam;
sınıf Güvenlik Denetleyicisi uzanır kontrolör
{
/ **
* @Yöntem({"ELDE ETMEK"})
* @Yol(“/giriş”, ad=”giriş”)
* @Şablon()
*/
halka açık işlev giriş(İstek $istek)
{
$ istek = bu $->getRequest();
$oturum = $request->getSession();
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$hata = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} başka {
$hata = $oturum->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
$param = dizi(
"son_kullanıcı adı" => $session->get(SecurityContext::LAST_USERNAME),
"hata" => $hata,
" İleti " => $istek->al(" İleti "),
);
if ($request->isXmlHttpRequest()) {
dönüş bu $-> render("GCDirectoryMainBundle:Security:login-ajax.html.twig", $paramlar);
}
dönüş $param;
}
/ **
* @Yöntem({"POSTALAMAK"})
* @Yol(“/login_check”, ad=”login_check”)
*/
halka açık işlev Kontrol()
{
atmak yeni Çalışma zamanı istisnası('Güvenlik duvarı yapılandırmanızda form_login kullanarak kontrol yolunu güvenlik duvarı tarafından işlenecek şekilde yapılandırmanız gerekir.');
}
/ **
* @Yöntem({"ELDE ETMEK"})
* @Yol(“/logout”, name=”logout”)
*/
halka açık işlev çıkış()
{
atmak yeni Çalışma zamanı istisnası('Güvenlik duvarı yapılandırmanızda oturumu kapatmayı etkinleştirmelisiniz.');
}
/ **
* @Yöntem({"ELDE ETMEK"})
* @Yol(“/reset”, ad=”reset”)
* @Güvenli(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Şablon()
*/
halka açık işlev ayarlamak() {
dönüş dizi();
}
/ **
* @Yöntem({"POSTALAMAK"})
* @Yol("/Sıfırla")
* @Güvenli(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
*/
halka açık işlev şimdi sıfırla(İstek $istek)
{
$params = $request->request->all();
if (!array_key_exists("giriş yapmak", $paramlar)) {
atmak yeni Istisna(“Giriş yapılmadı”);
}
$giriş = &$paramlar["giriş yapmak"];
$ em = bu $->konteyner->al("doctrine.orm.default_entity_manager");
$user = $em->getRepository("NamespaceMyBundle:Kullanıcı")->bulBirBy(dizi("giriş yapmak" => $giriş));
if ($kullanıcı == boş) {
dönüş bu $-> yönlendirme (bu $->oluşturUrl("giriş yapmak", dizi());
}
$şifre = “RandowParolam”;
$user->setPassword(bu $->konteyner->al("security.encoder_factory")->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->flush();
dönüş bu $-> yönlendirme (bu $->oluşturUrl("giriş yapmak", dizi());
}
/ **
* @Yöntem({"ELDE ETMEK"})
* @Yol(“/change”, name=”password-değiştir”)
* @Güvenli(roller=”IS_AUTHENTICATED_FULLY”)
* @Şablon()
*/
halka açık işlev değişiklik() {
dönüş dizi();
}
/ **
* @Yöntem({"POSTALAMAK"})
* @Yol("/değiştirmek")
* @Güvenli(roller=”IS_AUTHENTICATED_FULLY”)
* @Şablon()
*/
halka açık işlev şimdi değiştir(İstek $istek)
{
$params = $request->request->all();
if (!array_key_exists("akım", $paramlar)
|| !array_key_exists("yeni", $paramlar)
|| !array_key_exists(“yeni2”, $paramlar))
{
dönüş dizi("hata" => "Lütfen tüm alanları doldurun");
}
$ em = bu $->konteyner->al("doctrine.orm.default_entity_manager");
$kullanıcı = bu $->getUser();
$user_enkoderler = bu $->konteyner->al("security.encoder_factory")->getEncoder($user);
$user_repository = $em->getRepository("NamespaceMyBundle:Kullanıcı");
$current_password_encoded = $user_encoders->encodePassword($params["akım"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["yeni"], $user->getSalt());
if ($user_repository->findOneBy(dizi("şifre" => $current_password_encoded)) == boş) {
dönüş dizi("hata" => “Geçerli şifre yanlış”);
} elseif ($paramlar["yeni"] != $paramlar[“yeni2”]) {
dönüş dizi("hata" => "İki alan şifresi aynı değil");
}
$user->setPassword($new_password_encoded);
$em->persist($user);
$em->flush();
dönüş bu $-> yönlendirme (bu $->oluşturUrl("çıkış Yap", dizi());
}
/ **
* @Yöntem({"ELDE ETMEK"})
* @Yol(“/kayıt”, ad=”kayıt”)
* @Güvenli(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Şablon()
*/
halka açık işlev kayıt olmak()
{
$biçim = bu $->Form oluştur(yeni KullanıcıTürü(KullanıcıTürü::KAYIT), yeni Kullanıcı());
dönüş dizi(
"biçim" => $form->createView(),
);
}
/ **
* @Yöntem({"POSTALAMAK"})
* @Yol("/kayıt olmak")
* @Güvenli(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Şablon()
*/
halka açık işlev şimdi üye Ol(İstek $istek)
{
$params = $request->request->all()["formumun_adı"];
$biçim = bu $->Form oluştur(yeni KullanıcıTürü(KullanıcıTürü::KAYIT), yeni Kullanıcı());
$form->gönder($istek);
if (dizi_anahtar_var(“düz_şifre”, $paramlar) && array_key_exists("düz_şifre2", $paramlar) && $paramlar[“düz_şifre”] == $paramlar["düz_şifre2"]) {
if ($form->isValid()) {
$data = $form->getData();
$data->setPassword(bu $->konteyner->al("security.encoder_factory")->getEncoder($data)->encodePassword($params[“düz_şifre”], $data->getSalt()));
$em->persist($veri);
$em->flush();
dönüş bu $-> yönlendirme (bu $->oluşturUrl("giriş yapmak", dizi(" İleti " => "Hesabınızı doğrulamak için bir e-posta aldınız. »));
}
}
dönüş dizi(
"hatalar" => $paramlar[“düz_şifre”] == $paramlar["düz_şifre2"]? $form->getErrors(): dizi(“İki şifre aynı olmalı”),
"biçim" => $form->createView(),
);
}
/ **
* @Yöntem({"ELDE ETMEK"})
* @Yol(“/etkinleştir”, ad=”etkinleştir”)
* @Güvenli(roller=”IS_AUTHENTICATED_ANONYMOUSLY”)
* @Şablon()
*/
halka açık işlev aktive(İstek $istek) {
$param = dizi();
$token = $istek->sorgu->getir(« token »);
$ em = bu $->konteyner->al("doctrine.orm.default_entity_manager");
$user = $em->getRepository("NamespaceMyBundle:Kullanıcı")->bulBirBy(dizi(« token » => $token));
if ($kullanıcı != boş) {
$user->setActive(Kullanıcı::ACTIVE_ACTIVE);
$em->persist($user);
$em->flush();
$param["etkinleştir"] = gerçek;
} başka {
$param["etkinleştir"] = yanlış;
}
dönüş $param;
}
}

★ ★ ★ ★ ★