-
-
Notifications
You must be signed in to change notification settings - Fork 277
Expand file tree
/
Copy pathauthentication.texy
More file actions
179 lines (121 loc) · 7.43 KB
/
authentication.texy
File metadata and controls
179 lines (121 loc) · 7.43 KB
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
Autentificare
*************
Nette oferă o modalitate de a programa autentificarea pe paginile noastre, dar nu ne impune nimic. Implementarea depinde în totalitate de noi. Nette include interfața `Nette\Security\Authenticator`, care necesită doar o singură metodă `authenticate`, care verifică utilizatorul în orice mod dorim.
Există multe posibilități prin care un utilizator poate fi verificat. Cea mai frecventă metodă de autentificare este prin parolă (utilizatorul furnizează numele său sau e-mailul și parola), dar există și alte metode. Poate cunoașteți butoanele de tip "Conectare cu Facebook" sau autentificarea prin Google/Twitter/GitHub pe unele site-uri. Cu Nette, putem avea orice metodă de autentificare sau le putem combina. Depinde doar de noi.
În mod normal, am scrie propriul nostru authenticator, dar pentru acest blog mic și simplu vom folosi authenticatorul încorporat, care autentifică pe baza parolei și a numelui de utilizator stocate în fișierul de configurare. Este util în scopuri de testare. Adăugăm deci următoarea secțiune `security` în fișierul de configurare `config/common.neon`:
```neon .{file:config/common.neon}
security:
users:
admin: secret # utilizator 'admin', parolă 'secret'
```
Nette va crea automat un serviciu în containerul DI.
Formular de autentificare
=========================
Acum avem autentificarea pregătită și trebuie să pregătim interfața utilizator pentru autentificare. Creăm deci un nou presenter numit `SignPresenter`, care:
- afișează formularul de autentificare (cu nume de utilizator și parolă)
- după trimiterea formularului, verifică utilizatorul
- oferă posibilitatea de deconectare
Începem cu formularul de autentificare. Știm deja cum funcționează formularele în presenteri. Creăm deci presenterul `SignPresenter` și scriem metoda `createComponentSignInForm`. Ar trebui să arate cam așa:
```php .{file:app/Presentation/Sign/SignPresenter.php}
<?php
namespace App\Presentation\Sign;
use Nette;
use Nette\Application\UI\Form;
final class SignPresenter extends Nette\Application\UI\Presenter
{
protected function createComponentSignInForm(): Form
{
$form = new Form;
$form->addText('username', 'Nume utilizator:')
->setRequired('Vă rugăm să completați numele de utilizator.');
$form->addPassword('password', 'Parolă:')
->setRequired('Vă rugăm să completați parola.');
$form->addSubmit('send', 'Autentificare');
$form->onSuccess[] = $this->signInFormSucceeded(...);
return $form;
}
}
```
Există câmpuri pentru nume de utilizator și parolă.
Șablon
------
Formularul va fi redat în șablonul `in.latte`:
```latte .{file:app/Presentation/Sign/in.latte}
{block content}
<h1 n:block=title>Autentificare</h1>
{control signInForm}
```
Callback de autentificare
-------------------------
Apoi completăm callback-ul pentru autentificarea utilizatorului, care va fi apelat imediat după trimiterea cu succes a formularului.
Callback-ul preia pur și simplu numele de utilizator și parola pe care utilizatorul le-a completat și le transmite authenticatorului. După autentificare, redirecționăm către pagina principală.
```php .{file:app/Presentation/Sign/SignPresenter.php}
private function signInFormSucceeded(Form $form, \stdClass $data): void
{
try {
$this->getUser()->login($data->username, $data->password);
$this->redirect('Home:');
} catch (Nette\Security\AuthenticationException $e) {
$form->addError('Nume de utilizator sau parolă incorectă.');
}
}
```
Metoda [User::login() |api:Nette\Security\User::login()] aruncă o excepție dacă numele de utilizator și parola nu corespund datelor din fișierul de configurare. După cum știm deja, acest lucru poate duce la o pagină roșie de eroare sau, în mod de producție, la un mesaj care informează despre o eroare de server. Nu dorim însă acest lucru. De aceea, prindem această excepție și transmitem un mesaj de eroare frumos și prietenos pentru utilizator în formular.
Odată ce apare o eroare în formular, pagina cu formularul se redesenează și deasupra formularului se afișează un mesaj frumos care informează utilizatorul că a introdus un nume de utilizator sau o parolă greșită.
Securizarea presenterilor
=========================
Vom securiza formularul pentru adăugarea și editarea postărilor. Acesta este definit în presenterul `EditPresenter`. Scopul este de a restricționa accesul la pagină pentru utilizatorii care nu sunt autentificați.
Creăm metoda `startup()`, care se execută imediat la începutul [ciclului de viață al presenterului |application:presenters#Ciclul de viață al presenterului]. Aceasta redirecționează utilizatorii neautentificați către formularul de autentificare.
```php .{file:app/Presentation/Edit/EditPresenter.php}
public function startup(): void
{
parent::startup();
if (!$this->getUser()->isLoggedIn()) {
$this->redirect('Sign:in');
}
}
```
Ascunderea linkurilor
---------------------
Utilizatorul neautorizat nu mai poate vedea pagina *create* sau *edit*, dar încă poate vedea linkurile către acestea. Ar trebui să le ascundem și pe acestea. Un astfel de link se află în șablonul `app/Presentation/Home/default.latte` și ar trebui să fie vizibil doar pentru utilizatorii autentificați.
Îl putem ascunde folosind un *n:atribut* numit `n:if`. Dacă această condiție este `false`, întregul tag `<a>`, inclusiv conținutul, rămâne ascuns.
```latte
<a n:href="Edit:create" n:if="$user->isLoggedIn()">Creează postare</a>
```
ceea ce este o prescurtare a următoarei notații (a nu se confunda cu `tag-if`):
```latte
{if $user->isLoggedIn()}<a n:href="Edit:create">Creează postare</a>{/if}
```
În același mod, ascundem și linkul din șablonul `app/Presentation/Post/show.latte`.
Link către autentificare
========================
Cum ajungem de fapt la pagina de autentificare? Nu există niciun link care să ducă la ea. Așa că îl vom adăuga în șablonul `@layout.latte`. Încercați să găsiți un loc potrivit - poate fi aproape oriunde.
```latte .{file:app/Presentation/@layout.latte}
...
<ul class="navig">
<li><a n:href="Home:">Articole</a></li>
{if $user->isLoggedIn()}
<li><a n:href="Sign:out">Deconectare</a></li>
{else}
<li><a n:href="Sign:in">Autentificare</a></li>
{/if}
</ul>
...
```
Dacă utilizatorul nu este autentificat, se afișează linkul "Autentificare". În caz contrar, se afișează linkul "Deconectare". Vom adăuga și această acțiune în `SignPresenter`.
Deoarece redirecționăm imediat utilizatorul după deconectare, nu este nevoie de niciun șablon. Deconectarea arată astfel:
```php .{file:app/Presentation/Sign/SignPresenter.php}
public function actionOut(): void
{
$this->getUser()->logout();
$this->flashMessage('Deconectarea a avut succes.');
$this->redirect('Home:');
}
```
Se apelează doar metoda `logout()` și apoi se afișează un mesaj frumos care confirmă deconectarea cu succes.
Rezumat
=======
Avem un link pentru autentificare și, de asemenea, pentru deconectarea utilizatorului. Pentru verificare, am folosit authenticatorul încorporat și avem datele de autentificare în fișierul de configurare, deoarece este o aplicație simplă de test. Am securizat, de asemenea, formularele de editare, astfel încât doar utilizatorii autentificați pot adăuga și edita postări.
.[note]
Aici puteți citi mai multe despre [autentificarea utilizatorilor |security:authentication] și [Autorizarea permisiunilor |security:authorization].
{{priority: -1}}