Большинству неосновных многопользовательских приложений требуются некоторые роли и уровни разрешений. Если вы когда-либо использовали WordPress, вы, должно быть, заметили, что у них есть супер-администратор, администратор, редактор, автор и т. Д. Упрощение разработки и интеграции системы разрешений — это то, чего пытается добиться пакет Sentinel от Cartalyst . Пакет предоставляет API для работы с пользователями, группами, разрешениями и т. Д. В этой статье мы будем использовать его для создания небольшого демонстрационного приложения.
Настройка среды
Для нашего примера приложения в этом руководстве мы будем использовать микро-фреймворк Slim и Vagrant . Вы можете проверить финальную демонстрацию на Github, чтобы увидеть результат. Начнем с того, что сначала потребуем необходимые пакеты:
composer require slim / slim :~ 2.0 composer require twig / twig :~ 1. * composer require cartalyst / sentinel : 2.0 .*
Sentinel предлагает установить Illuminate Eloquent , Illuminate Events , Symfony Http Foundation и ircmaxell password-compat, поэтому давайте добавим их в проект.
composer require illuminate / database illuminate / events symfony / http - foundation ircmaxell / password - compat
Поскольку работа с пользователями, группами и разрешениями требует некоторого взаимодействия с базой данных, нам необходимо создать нашу базу данных с необходимыми таблицами. Если вы используете Laravel, вы можете установить базу данных с помощью команды migrate.
php artisan vendor : publish -- provider = "Cartalyst\Sentinel\Laravel\SentinelServiceProvider" php artisan migrate
Если нет, вам придется сделать это вручную, используя следующие шаги. Подробнее об установке базы данных вы можете прочитать в документации .
- Откройте
vendor/cartalyst/sentinel/schema/mysql.sql
, добавьтеuse DATABASENAME;
в верхней части файла и сохраните. - Загрузите ваш файл в MySQL с помощью команды
mysql -u root -p < vendor/cartalyst/sentinel/schema/mysql.sql
и введите пароль, если необходимо, или просто импортируйте файл, используя ваш любимый редактор / инспектор SQL (например, PhpMyAdmin, Sequel) Pro и т. Д.).
Наконец, давайте загрузим наше приложение с файлом public/index.php
:
<? php require_once __DIR__ . '/../vendor/autoload.php' ; $app = new \Slim\Slim ();
//register bindings include_once __DIR__ . '/../app/bootstrap/container.php' ; include_once __DIR__ . '/../app/routes.php' ; $app -> run ();
Привязки контейнера
Внутри нашего app/bootstrap/container.php
мы определим привязки нашего контейнера.
$app -> container -> twigLoader = new Twig_Loader_Filesystem ( __DIR__ . '/../views' ); $app -> container -> twig = new Twig_Environment ( $app -> container -> twigLoader , array (
'cache' => false ,
));
Переменная $app
является контейнером Slim
. Поскольку мы решили использовать Eloquent для взаимодействия с нашей базой данных, нам нужно указать конфигурацию соединения.
// app/bootstrap/container.php $capsule = new \Illuminate\Database\Capsule\Manager (); $capsule -> addConnection ([
'driver' => 'mysql' ,
'host' => 'localhost' ,
'database' => 'capsule' ,
'username' => 'root' ,
'password' => 'root' ,
'charset' => 'utf8' ,
'collation' => 'utf8_unicode_ci' ,
]); $capsule -> bootEloquent ();
После загрузки Eloquent остается только привязать Sentinel к контейнеру.
// app/bootstrap/container.php $app -> container -> sentinel = ( new \Cartalyst\Sentinel\Native\Facades\Sentinel ())-> getSentinel ();
Если вы предпочитаете использовать статические вызовы, вы можете использовать его напрямую. ( Sentinel::authenticate($credentials)
)
Создание ролей
Первым шагом является определение наших групп разрешений. У нас есть роль admin
которая дает пользователю право создавать, обновлять и удалять пользователей. С другой стороны, роль user
дает только разрешение на обновление пользователей.
$app -> container -> sentinel -> getRoleRepository ()-> createModel ()-> create ( array (
'name' => 'Admin' ,
'slug' => 'admin' ,
'permissions' => array (
'user.create' => true ,
'user.update' => true ,
'user.delete' => true
),
)); $app -> container -> sentinel -> getRoleRepository ()-> createModel ()-> create ( array (
'name' => 'User' ,
'slug' => 'user' ,
'permissions' => array (
'user.update' => true
),
));
Этот код является временным, и его можно поместить в index.php
, запустить один раз, а затем удалить. Его единственная цель — создать роли в базе данных.
Страница регистрации
У нас есть два варианта при создании страницы регистрации. Мы можем использовать подтверждение по электронной почте или напрямую установить пользователя как проверенного.
// app/routes.php $app -> get ( '/' , function () use ( $app ) { $app -> twig -> display ( 'home.html.twig' );
});
Наша домашняя страница содержит форму и набор полей для данных пользователя (имя, фамилия, адрес электронной почты, пароль и подтверждение пароля). Проверьте исходный код просмотра файлов здесь .
Затем давайте определим домашний маршрут POST
.
// app/routes.php $app -> post ( '/' , function () use ( $app ) {
// we leave validation for another time $data = $app -> request -> post (); $role = $app -> container -> sentinel -> findRoleByName ( 'User' );
if ( $app -> container -> sentinel -> findByCredentials ([
'login' => $data [ 'email' ],
])) { echo 'User already exists with this email.' ;
return ;
} $user = $app -> container -> sentinel -> create ([
'first_name' => $data [ 'firstname' ],
'last_name' => $data [ 'lastname' ],
'email' => $data [ 'email' ],
'password' => $data [ 'password' ],
'permissions' => [
'user.delete' => 0 ,
],
]);
// attach the user to the role $role -> users ()-> attach ( $user );
// create a new activation for the registered user $activation = ( new Cartalyst \Sentinel\Activations\IlluminateActivationRepository )-> create ( $user ); mail ( $data [ 'email' ], "Activate your account" , "Click on the link below \n <a href='http://vaprobash.dev/user/activate?code={$activation->code}&login={$user->id}'>Activate your account</a>" ); echo "Please check your email to complete your account registration." ;
});
После получения данных запроса и разрешения Sentinel из контейнера мы выбираем роль, которую хотим назначить новому пользователю. Вы можете запрашивать роли по имени, слаг или по идентификатору. Подробнее об этом в документации . Затем мы проверяем, зарегистрирован ли новый пользователь, затем создаем нового пользователя, используя данные запроса, назначаем ему роль User
и создаем новую активацию. Процесс активации не является обязательным, мы поговорим об этом позже. Мы пропустили процесс проверки, чтобы сохранить простоту функции.
права доступа
Роль пользователя дает пользователям разрешение на обновление. Но что, если мы хотим добавить или переопределить некоторые разрешения?
$user = $app -> container -> sentinel -> create ([
'first_name' => $data [ 'firstname' ],
'last_name' => $data [ 'lastname' ],
'email' => $data [ 'email' ],
'password' => $data [ 'password' ],
'permissions' => [
'user.update' => false ,
'user.create' => true
],
]);
У Sentinel есть два метода для работы с разрешениями: стандартный или строгий. Для стандартного метода вы можете дать пользователю возможность создавать новых пользователей напрямую ( 'user.create': true
), но когда вы хотите отказать в разрешении роли, вам просто нужно дать ему значение false
в разрешениях пользователя , Строгий метод будет отменять разрешение, если в любом месте установлено значение false
. Вы можете прочитать больше о разрешениях в документации .
Активация пользователя
После сохранения пользователя в базе данных вам необходимо отправить ссылку активации на электронную почту пользователя.
У нас есть два способа реализовать процесс активации. Первый отправит код и идентификатор пользователя по электронной почте, а второй отправит только код активации.
// app/routes.php $app -> post ( '/' , function () use ( $app ) {
//... $activation = ( new Cartalyst \Sentinel\Activations\IlluminateActivationRepository )-> create ( $user ); mail ( $data [ 'email' ], "Activate your account" , "Click on the link below \n <a href='http://vaprobash.dev/user/activate?code={$activation->code}&login={$user->id}'>Activate your account</a>" ); echo "Please check your email to complete your account registration." ;
});
Метод create
в IlluminateActivationRepository
возвращает запись базы данных, содержащую код активации. Теперь нам нужно создать новый маршрут для перехвата запроса на проверку аккаунта.
// app/routes.php $app -> get ( '/user/activate' , function () use ( $app ) { $code = $app -> request -> get ( 'code' ); $login = $app -> request -> get ( 'login' ); $activation = new Cartalyst \Sentinel\Activations\IlluminateActivationRepository ;
if (!( $user = $app -> sentinel -> findById ( $login )))
{ echo "User not found!" ;
return ;
}
if (! $activation -> complete ( $user , $code ))
{
if ( $activation -> completed ( $user ))
{ echo 'User is already activated. Try to log in.' ;
return ;
} echo "Activation error!" ;
return ;
} echo 'Your account has been activated. Log into your account.' ;
return ;
});
Первый шаг — проверить, существует ли пользователь. Затем мы пытаемся завершить активацию. В случае ошибки мы проверяем, был ли пользователь уже активирован.
// app/routes.php $app -> get ( '/user/activate' , function () use ( $app ) { $code = $app -> request -> get ( 'code' ); $activationRepository = new Cartalyst \Sentinel\Activations\IlluminateActivationRepository ; $activation = Cartalyst \Sentinel\Activations\EloquentActivation :: where ( "code" , $code )-> first ();
if (! $activation )
{ echo "Activation error!" ;
return ;
} $user = $app -> container -> sentinel -> findById ( $activation -> user_id );
if (! $user )
{ echo "User not found!" ;
return ;
}
if (! $activationRepository -> complete ( $user , $code ))
{
if ( $activationRepository -> completed ( $user ))
{ echo 'User is already activated. Try to log in.' ;
return ;
} echo "Activation error!" ;
return ;
} echo 'Your account has been activated. Log in to your account.' ;
return ;
});
Первым шагом является получение записи активации с использованием параметра code
, затем мы получаем пользователя с использованием идентификатора пользователя из записи активации, и последняя часть аналогична первому способу. Подробнее об активации вы можете прочитать в документации .
Я предпочитаю использовать второй метод для процесса активации, и я всегда избегаю посылать ненужные детали пользователю.
Страница авторизации
Страница входа в систему содержит поле электронной почты, пароль, и пользователь может запомнить его.
// app/routes.php $app -> get ( '/login' , function () use ( $app ) { $app -> twig -> display ( 'login.html.twig' );
});
После получения электронной почты и пароля пользователя мы можем передать их методу authenticate
. Это может вызвать исключение в зависимости от ошибки ( ThrottlingException
, NotActivatedException
и т. Д.). Вы можете прочитать больше о методе authenticate
в документации . Тем не менее, у вас может быть поле remember me
для автоматической регистрации пользователя в будущем. Метод authenticateAndRemember
похож на метод authenticate
и по умолчанию устанавливает для параметра Запомнить меня значение true
.
// app/routes.php $app -> post ( '/login' , function () use ( $app ) { $data = $app -> request -> post (); $remember = isset ( $data [ 'remember' ]) && $data [ 'remember' ] == 'on' ? true : false ;
try {
if (! $app -> container -> sentinel -> authenticate ([
'email' => $data [ 'email' ],
'password' => $data [ 'password' ],
], $remember )) { echo 'Invalid email or password.' ;
return ;
} else { echo "You're logged in" ;
return ;
}
} catch ( Cartalyst \Sentinel\Checkpoints\ThrottlingException $ex ) { echo "Too many attempts!" ;
return ;
} catch ( Cartalyst \Sentinel\Checkpoints\NotActivatedException $ex ){ echo "Please activate your account before trying to log in" ;
return ;
}
});
Метод authenticate
вернет пользователя в случае успеха или false при ошибке, но важная часть заключается в том, что он может выдать исключение в зависимости от включенных контрольных точек , которые похожи на промежуточное программное обеспечение, которое перехватывает процесс входа в систему и решает, можно ли продолжить или нет. В этом случае у нас может быть ThrottlingException
в случае неправомерных попыток входа или NotActivatedException
если пользователь еще не активирован. Вы можете настроить включенные контрольные точки в vendor/cartalyst/sentinel/src/config
в разделе checkpoints
.
Выйти
Выйти из текущего пользователя действительно просто.
// app/routes.php $app -> get ( '/logout' , function () use ( $app ) { $app -> container -> sentinel -> logout (); echo 'Logged out successfully.' ;
});
Страница администратора
Наша страница администратора не содержит никакого просмотра контента. Мы просто собираемся проверить, подключен ли пользователь, получить зарегистрированного пользователя и затем проверить, есть ли у него необходимые разрешения для доступа к странице.
// app/routes.php $app -> get ( '/admin/users' , function () use ( $app ) { $loggedUser = $app -> container -> sentinel -> check ();
if (! $loggedUser ) { echo 'You need to be logged in to access this page.' ;
return ;
}
if (! $loggedUser -> hasAccess ( 'user.*' )) { echo "You don't have the permission to access this page." ;
return ;
} echo 'Welcome to the admin page.' ;
});
Метод check
возвращает зарегистрированного пользователя или false
. Если у нас есть пользователь, мы вызываем метод hasAccess
с необходимыми разрешениями. Псевдоним *
выбирает любое разрешение. Вы можете использовать user.update
или user.delete
зависимости от необходимого разрешения для доступа к ресурсу.
Завершение
Пакет Sentinel устраняет трудности, связанные с разрешениями пользователей и управлением ролями. Он также предлагает возможность добавлять напоминания пароля, хэши паролей и т. Д. Обязательно ознакомьтесь с документацией для получения более подробной информации, посмотрите окончательный продукт на Github и, если у вас есть какие-либо вопросы или комментарии, не стесняйтесь их публиковать. ниже.