Удостоверяване
Nette предоставя начин за програмиране на удостоверяване на нашия
уебсайт, но не ни принуждава да правим нищо. Изпълнението зависи от нас.
Nette включва интерфейс Nette\Security\Authenticator
, който изисква само един
метод authenticate
за удостоверяване на потребителя, както искаме.
Има много начини, по които потребителят може да се удостовери. Най-разпространеният метод е удостоверяване с парола (потребителят посочва своето име или имейл и парола), но има и други методи. Може би сте виждали бутони като “Влезте във Facebook/Google/Twitter/GitHub и т.н.” в много уебсайтове. С Nette можем да използваме всеки метод за влизане, който желаем, и можем да ги комбинираме. Това зависи от нас.
Обикновено пишем собствен автентификатор, но за този прост блог ще
използваме вградения автентификатор, който влиза в системата въз
основа на паролата и потребителското име, записани в конфигурационния
файл. Това работи добре за целите на тестването. Добавяне на раздел
security в конфигурационния файл config/common.neon
:
security:
users:
admin: secret # вход 'admin', парола 'secret'
Nette автоматично ще създаде услуга в контейнера DI.
Регистрационен формуляр
Вече имаме готово удостоверяване и трябва да подготвим потребителския интерфейс за влизане в системата. Затова нека създадем нов презентатор, наречен SignPresenter, който ще:
- показване на формуляра за вход (изискват се потребителско име и парола)
- Удостоверяване на автентичността на потребителя при подаване на формуляра
- Осигуряване на изход от системата
Нека започнем с формата за вход. Вече знаете как работят формулярите
в програмата Presenter. Създайте SignPresenter
и метод
createComponentSignInForm
. Това трябва да изглежда по следния начин:
<?php
namespace App\UI\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', 'Имя пользователя:')
->setRequired('Пожалуйста, введите ваше имя.');
$form->addPassword('password', 'Пароль:')
->setRequired('Пожалуйста, введите ваш пароль.');
$form->addSubmit('send', 'Войти');
$form->onSuccess[] = $this->signInFormSucceeded(...);
return $form;
}
}
Вече имаме въведени потребителско име и парола.
Шаблон
Формулярът ще бъде показан в шаблона app/UI/Sign/in.latte
.
{block content}
<h1 n:block=title>Войти</h1>
{control signInForm}
Обслужване на вход
След това ще добавим обработчик на формуляра за влизане на потребителя, който ще бъде извикан веднага след успешното изпращане на формуляра.
Обслужващият модул просто взема потребителското име и паролата, които потребителят е въвел, и ги предава на удостоверителя. След като влезете в системата, ще ви пренасочим към началната страница:
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('Неправильные логин или пароль.');
}
}
Методът User::login( ) трябва да хвърли изключение, ако потребителското име или паролата не съвпадат с тези, които определихме по-рано. Както вече знаем, това ще доведе до червена страница за грешка на Tracy или, в производствен режим, до съобщение за грешка на вътрешния сървър. Но ние не искаме това. Така че прихващаме изключението и добавяме хубаво, дружелюбно съобщение за грешка към формуляра.
Когато във формуляра възникне грешка, страницата на формуляра ще бъде показана отново, а над формуляра ще се появи хубаво съобщение, което ще информира потребителя, че е въвел грешно потребителско име или парола.
Сигурност на водещия
Подсигурете формата за добавяне и редактиране на публикации. Целта е да се предотврати достъпът на неоторизирани потребители до страницата.
Ще създадем метод startup()
, който се изпълнява веднага в началото
на жизнения цикъл на
презентатора. Това пренасочва нерегистрираните потребители към
формата за вход.
public function startup(): void
{
parent::startup();
if (!$this->getUser()->isLoggedIn()) {
$this->redirect('Sign:in');
}
}
Скриване на връзки
Неоторизиран потребител вече не може да вижда страниците за
създаване и редактиране, но все още може да вижда връзките, които сочат
към тях. Нека скрием и тях. Една такава връзка се намира на адрес
app/UI/Home/default.latte
, като тя трябва да бъде видима само ако
потребителят е влязъл в системата.
Можем да го скрием, като използваме n:атрибута, наречен n:if
.
Ако изявлението в него е false
, тогава целият таг <a>
и
съдържанието му няма да бъде показано:
<a n:href="Edit:create" n:if="$user->isLoggedIn()">Создать пост</a>
това е съкращение (да не се бърка с tag-if
):
{if $user->isLoggedIn()}<a n:href="Edit:create">Создать пост</a>{/if}
По същия начин скрийте връзката за редактиране, намираща се на адрес
app/UI/Post/show.latte
.
Връзка към формуляра за влизане
Здравейте, но как да стигнем до страницата за вход? Няма връзка, която
да сочи към него. Нека да го добавим към файла с шаблона
app/UI/@layout.latte
. Опитайте се да намерите добро място, може да е всяко
място, което ви харесва най-много.
...
<ul class="navig">
<li><a n:href="Home:">Главная</a></li>
{if $user->isLoggedIn()}
<li><a n:href="Sign:out">Выйти</a></li>
{else}
<li><a n:href="Sign:in">Войти</a></li>
{/if}
</ul>
...
Ако потребителят все още не е влязъл в системата, той ще види връзка
“Вход”. В противен случай ще се вижда връзката “Изход”. Добавете това
действие в SignPresenter
.
Действието за излизане от системата изглежда по следния начин и тъй като пренасочваме потребителя веднага, няма нужда от шаблон на изгледа:
public function actionOut(): void
{
$this->getUser()->logout();
$this->flashMessage('Вы вышли.');
$this->redirect('Home:');
}
Той просто извиква метода logout()
и след това показва на
потребителя хубаво съобщение.
За да обобщим
Имаме връзка за влизане и връзка за излизане на потребителя. Използвахме вградения автентификатор за удостоверяване, а данните за вход са в конфигурационния файл, тъй като това е просто тестово приложение. Също така защитихме формите за редактиране, така че само влезлите в системата потребители да могат да добавят и редактират съобщения.
Тук можете да прочетете повече за user login и authorization.