Authentikáció
A Nette módot biztosít az authentikáció programozására az oldalainkon, de semmire sem kényszerít minket. Az
implementáció kizárólag rajtunk múlik. A Nette tartalmazza a Nette\Security\Authenticator
interfészt, amely
csak egyetlen authenticate
metódust követel meg, amely a felhasználót bármilyen általunk kívánt módon
ellenőrzi.
Számos lehetőség van arra, hogyan lehet egy felhasználót hitelesíteni. A leggyakoribb hitelesítési mód a jelszó használata (a felhasználó megadja a nevét vagy e-mail címét és jelszavát), de vannak más módszerek is. Talán ismeri a “Bejelentkezés Facebookkal” típusú gombokat, vagy a Google/Twitter/GitHub segítségével történő bejelentkezést néhány oldalon. A Nette segítségével bármilyen bejelentkezési módszerünk lehet, vagy akár kombinálhatjuk is őket. Ez csak rajtunk múlik.
Általában saját authentikátort írnánk, de ehhez az egyszerű kis bloghoz a beépített authentikátort fogjuk használni,
amely a konfigurációs fájlban tárolt jelszó és felhasználónév alapján jelentkeztet be. Tesztelési célokra jól
használható. Adjunk hozzá tehát a következő security
szekciót a config/common.neon
konfigurációs fájlhoz:
security:
users:
admin: secret # felhasználó 'admin', jelszó 'secret'
A Nette automatikusan létrehoz egy szolgáltatást a DI konténerben.
Bejelentkezési űrlap
Most már készen áll az authentikáció, és elő kell készítenünk a felhasználói felületet a bejelentkezéshez.
Hozzunk létre tehát egy új presentert SignPresenter
néven, amely:
- megjeleníti a bejelentkezési űrlapot (felhasználónévvel és jelszóval)
- az űrlap elküldése után ellenőrzi a felhasználót
- lehetőséget biztosít a kijelentkezésre
Kezdjük a bejelentkezési űrlappal. Már tudjuk, hogyan működnek az űrlapok a presenterekben. Hozzunk létre tehát egy
SignPresenter
presentert, és írjuk meg a createComponentSignInForm
metódust. Valahogy így kellene
kinéznie:
<?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', 'Felhasználónév:')
->setRequired('Kérjük, töltse ki a felhasználónevét.');
$form->addPassword('password', 'Jelszó:')
->setRequired('Kérjük, töltse ki a jelszavát.');
$form->addSubmit('send', 'Bejelentkezés');
$form->onSuccess[] = $this->signInFormSucceeded(...);
return $form;
}
}
Vannak mezők a felhasználónévhez és a jelszóhoz.
Sablon
Az űrlap az in.latte
sablonban fog renderelődni:
{block content}
<h1 n:block=title>Bejelentkezés</h1>
{control signInForm}
Bejelentkezési callback
Ezután hozzáadjuk a felhasználó bejelentkezéséhez szükséges callbacket, amely az űrlap sikeres elküldése után azonnal meghívódik.
A callback csak átveszi a felhasználó által kitöltött felhasználónevet és jelszót, és átadja azokat az authentikátornak. Bejelentkezés után átirányítunk a kezdőoldalra.
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('Helytelen felhasználónév vagy jelszó.');
}
}
A User::login() metódus kivételt dob, ha a felhasználónév és a jelszó nem egyezik a konfigurációs fájlban szereplő adatokkal. Ahogy már tudjuk, ez piros hibaoldalt eredményezhet, vagy éles módban egy szerverhibáról tájékoztató üzenetet. Ezt azonban nem akarjuk. Ezért elkapjuk ezt a kivételt, és egy szép, felhasználóbarát hibaüzenetet adunk át az űrlapnak.
Amint hiba történik az űrlapon, az űrlapot tartalmazó oldal újrarajzolódik, és az űrlap felett megjelenik egy szép üzenet, amely tájékoztatja a felhasználót, hogy rossz felhasználónevet vagy jelszót adott meg.
Presenterek védelme
Biztosítsuk a bejegyzések hozzáadására és szerkesztésére szolgáló űrlapot. Ez az EditPresenter
presenterben van definiálva. A cél az, hogy megakadályozzuk a nem bejelentkezett felhasználók hozzáférését az
oldalhoz.
Létrehozunk egy startup()
metódust, amely azonnal elindul a presenter életciklusának elején. Ez
átirányítja a nem bejelentkezett felhasználókat a bejelentkezési űrlapra.
public function startup(): void
{
parent::startup();
if (!$this->getUser()->isLoggedIn()) {
$this->redirect('Sign:in');
}
}
Linkek elrejtése
Az illetéktelen felhasználó már nem láthatja a create vagy edit oldalt, de továbbra is láthatja a rájuk
mutató linkeket. Ezeket is el kellene rejtenünk. Egy ilyen link az app/Presentation/Home/default.latte
sablonban
található, és csak a bejelentkezett felhasználók láthatják.
Elrejthetjük egy n:attribútum használatával, amelynek neve n:if
. Ha ez a feltétel false
,
az egész <a>
tag, beleértve a tartalmát is, rejtve marad.
<a n:href="Edit:create" n:if="$user->isLoggedIn()">Bejegyzés létrehozása</a>
ami a következő jelölés rövidítése (nem összetévesztendő a tag-if
-fel):
{if $user->isLoggedIn()}<a n:href="Edit:create">Bejegyzés létrehozása</a>{/if}
Ugyanígy elrejtjük a linket az app/Presentation/Post/show.latte
sablonban is.
Bejelentkezési link
Hogyan jutunk el valójában a bejelentkezési oldalra? Nincs rá mutató link. Adjunk hozzá egyet az
@layout.latte
sablonhoz. Próbáljon megfelelő helyet találni – szinte bárhol lehet.
...
<ul class="navig">
<li><a n:href="Home:">Cikkek</a></li>
{if $user->isLoggedIn()}
<li><a n:href="Sign:out">Kijelentkezés</a></li>
{else}
<li><a n:href="Sign:in">Bejelentkezés</a></li>
{/if}
</ul>
...
Ha a felhasználó nincs bejelentkezve, a “Bejelentkezés” link jelenik meg. Ellenkező esetben a “Kijelentkezés” link
jelenik meg. Ezt az akciót is hozzáadjuk a SignPresenter
-hez.
Mivel a felhasználót kijelentkezés után azonnal átirányítjuk, nincs szükség sablonra. A kijelentkezés így néz ki:
public function actionOut(): void
{
$this->getUser()->logout();
$this->flashMessage('A kijelentkezés sikeres volt.');
$this->redirect('Home:');
}
Csak a logout()
metódus hívódik meg, majd megjelenik egy szép üzenet, amely megerősíti a sikeres
kijelentkezést.
Összegzés
Van linkünk a bejelentkezéshez és a felhasználó kijelentkezéséhez is. Az ellenőrzéshez a beépített authentikátort használtuk, és a bejelentkezési adatokat a konfigurációs fájlban tároljuk, mivel ez egy egyszerű tesztalkalmazás. Biztosítottuk a szerkesztési űrlapokat is, így csak a bejelentkezett felhasználók adhatnak hozzá és szerkeszthetnek bejegyzéseket.
Itt olvashat többet a felhasználók bejelentkeztetéséről és a jogosultságok ellenőrzéséről.