BugTracker: авторизация и аутентификация (часть восьмая)

Владимир | | CodeIgniter, MySQL, PHP, Web разработка.

Приветствую всех читателей!

В этой части мы рассмотрим создание не сложной системы авторизации пользователей нашего баг трекера.

Для начала сформулируем задачу.

Как вы, наверное, помните, оставить сообщение о найденном баге или комментарий к нему может кто угодно. Но удалять записи и комментарии могут только администраторы.

На практике это будет выглядеть следующим образом. Администратор при входе вводит имя и пароль. Баг трекер их проверяет и, если они совпадают с записанными в базе данных, добавляет к каждому багу и комментарию ссылку «Удалить».

Кроме того, при выполнении каждой операции удаления необходимо проверить является ли текущий пользователь администратором.

Для справки. Эти проверки называются аутентификация и авторизация.

Авторизация (англ. authorization) — процесс предоставления определенному лицу прав на выполнение некоторых действий.

Аутентификация (англ. Authentication) — процедура проверки соответствия некоего лица и его учетной записи в компьютерной системе.

(цитаты из википедии)

Таким образом, при входе в систему нам нужно аутентифицировать администратора, а при выполнении им операции – авторизовать.

Задача, в общем-то, стандартная и для её решения написано множество библиотек разной степени сложности.

Прежде чем переходить к выбору библиотеки, перечислим функции, которые нужны для разделения прав в нашем баг трекере.

1) Создание учетной записи в базе данных.

2) Проверка имени и пароля при входе в систему (аутентификация).

3) Проверка прав пользователя на выполнение операции (авторизация).

Требования минимальные и не сложно было бы реализовать такую систему самостоятельно. Но зачем «изобретать велосипед» если есть куча готовых решений?

Для этого проекта я решил использовать библиотеку под названием Redux. Каких-то особых причин, по которым я на ней остановился, нет. Просто видел несколько хороших отзывов, и захотелось поэкспериментировать.

На данный момент есть две версии библиотеки: 1.4а (стабильная) и 2 (бета). Вторая по своим возможностям мне понравилась больше, поэтому и использовал я именно её. Но бета есть бета, и сразу обнаружилось несколько недостатков.

Самое главное, в архиве 2-ой версии нет документации, есть только демонстрационный пример. Полноценная справка написана для версии 1.4, причем очень хорошая, сделана в том же стиле, что и тьюториал CodeIgniter.

Используя пример и справку из версии 1.4, разобраться не сложно.

Теперь рассмотрим, что нужно сделать для подключения этой библиотеки к нашему приложению.

1) Скачать и распаковать архив.

2) Скопировать 3 файла:
\application\config\redux_auth.php
\application\models\redux_auth_model.php
\application\libraries\redux_auth.php

3) Импортировать файл database.sql в базу данных. При этом будут созданы несколько таблиц.

4) Настроить библиотеку. Для этого, открываем файл \application\config\redux_auth.php и изменяем соответствующие значения. Здесь я только отключил активацию по email.

$config['email_activation'] = false;

5) Создаем группу, которая используется по-умолчанию. В файле \application\config\redux_auth.php есть параметр

$config['default_group'] = 'member';

Чтобы библиотека нормально заработала нужно создать в таблице groups запись с название этой группы. Т.е. name='member', description='member group description'.

6) В таблице sessions изменяем сравнение для поля user_data на utf8_general_ci, иначе будут проблемы с кириллицей.

7) Открываем файл \application\config\config.php и находим раздел с настройками сессий. Я изменил

$config['sess_encrypt_cookie']	= TRUE;
$config['sess_use_database']	= TRUE;
$config['sess_table_name']		= 'sessions';
$config['sess_match_ip']		= TRUE;
$config['sess_match_useragent']	= TRUE;

8 ) Добавляем библиотеку в автозагрузку (файл \application\config\autoload.php).

$autoload['libraries'] = array('database', 'session', 'redux_auth');
$autoload['model'] = array('redux_auth_model');

Теперь нужно создать учетную запись администратора.

Т.к. в базе данных храниться не сам пароль, а его хеш, то удобнее всего добавить запись средствами библиотеки, а не вручную.

Для этого, добавим в контроллер (bugtracker) метод register.

function register() {
	$this->redux_auth->register('admin', 'password', 'admin@bugtracker.local');
}

Заходим один раз на страницу bugtracker.local/bugtracker/register и в базе данных появляется новая запись.

После этого метод можно удалить.

Обратите внимание! Для аутентификации Redux использует не имя (admin), а email.

Создаем страницу с формой входа.

Для этого добавляем в контроллер метод login.

function login() {
	if ($this->redux_auth->logged_in()) {
		redirect('bugtracker/page');
	}
	$pageData['title'] = 'Login';
	$this->load->view('header', $pageData);
	$this->load->view('login');
	$this->load->view('footer');
}

Этот метод просто создает страницу с формой. Сама форма находится в представлении \views\login.php.

Перед формированием страницы мы с помощью метода logged_in() проверяем, выполнил ли вход данный пользователь (строки 2-4). И если да, то отправляем его на главную страницу багтрекера.

Теперь рассмотрим представление (\views\login.php)

<?php
$mes = $this->session->flashdata('message');
if (!empty($mes)) {
	echo '<div id="infoMessage">'.$mes.'</div>';
}
?>
<?php echo form_open('bugtracker/checklogin', array('id'=>'fLogin')); ?>
	<p>
	<label for="email">eMail</label>
	<input type="text" name="email" id="email" value="<?php echo set_value('email'); ?>" />
	</p>
	<?php echo form_error('eMail'); ?>
	<p class="even">
	<label for="password">Пароль</label>
	<input type="password" name="password" id="password" value="" />
	</p>
	<?php echo form_error('password'); ?>
	<p><input type="submit" name="bLogin" id="bLogin" class="bLogin" value="Войти" />
	</p>
</form>

Тут все просто. Мы создаем обычную форму с двумя полями: «eMail» и «Пароль». После нажатия на кнопку «Войти» данные будут отправлены методу checklogin контроллера (строка 7).

Этот метод выполняет аутентификацию пользователя. Проще говоря проверяет соответствие email'а паролю.

function checklogin() {
	$this->load->library('form_validation');
	$this->form_validation->set_rules('email', 'lang:email', 'required|valid_email');
	$this->form_validation->set_rules('password', 'lang:password', 'required');
	$this->form_validation->set_error_delimiters('<div class="fErrMessage">', '</div>');
	
	if ($this->form_validation->run() == false)
	{
		$pageData['title'] = 'Login error';
		$this->load->view('header', $pageData);
		$this->load->view('login');
		$this->load->view('footer');
	}
	else
	{
		$login    = $this->input->post('email');
		$password = $this->input->post('password');
		
		if ($this->redux_auth->login($login, $password)) {
			$this->session->set_flashdata('message', 'Привет, '.$login);
			redirect('bugtracker/page');
		}
		else {
			$this->session->set_flashdata('message', 'Неверная пара логин/пароль, попробуйте ещё раз');
			redirect('bugtracker/login');
		}
	}
}

Прежде всего, мы поверяем корректность заполнения формы. Для этого создаем правила (строки 3, 4) и выполняем проверку (сторока 7). Если форма заполнена правильно (данные введены), то с помощью метода login($login, $password) (строка 19) ищем посетителя в базе данных.

Если соответствующая запись в БД будет найдена, отправляем его на главную (строка 21). При этом библиотека сама сохранит данные этого пользователя в сессии. И в дальнейшем мы сможем использовать метод logged_in() для авторизации пользователя.

Если email или пароль введены не правильно, то показываем посетителю форму ещё раз с предложением попробовать ещё раз.

Теперь рассмотрим метод удаления записи о баге.

function deletebug($bugId) {
	if ($this->redux_auth->logged_in()) {
		if ($this->mbug->delete($bugId)) {
			$this->session->set_flashdata('message', 'Баг удален');
			redirect($this->session->userdata('prev_page'));
		}
		else {
			$this->session->set_flashdata('message', 'При удалении бага возникла ошибка');
			redirect($this->session->userdata('prev_page'));
		}
	}
	else {
		$this->session->set_flashdata('message', 'Вы должны войти для того, чтобы выполнить это действие');
		redirect('bugtracker/login');
	}
}

Во второй строке мы выполняем авторизацию пользователя. И в зависимости от её результатов либо удаляем баг (строки 3-10), либо отправляем посетителя на страницу с формой входа (строки 13, 14).

Т.е. если кто-то, не выполнив вход, попробует отправить запрос bugtracker.local/bugtracker/deletebug/1, то он увидит сообщение 'Вы должны войти для того, чтобы выполнить это действие' и форму ввода email и пароля.

В шаблонах багов и комментариев (bug_tpl.php и comment_tpl.php) также добавим несколько строк:

if ($this->redux_auth->logged_in()) {
	echo '<p class="deleteBug">'.anchor('bugtracker/deletebug/{id}', 'Удалить').'</p>';
}

Таким образом, администраторы увидят ссылку «Удалить» рядом с каждым багом и комментарием.

Примечание. Подробнее об этих шаблонах можно почитать в четвертой части.

И последний момент. Нужно дать возможность администратору выйти из приложения.

Для этого создаем метод logout.

function logout()
{
	$this->redux_auth->logout();
	$this->session->set_flashdata('message', 'Вы вышли из администраторского режима');
	redirect('bugtracker/page');
}

После выхода (строка 2) мы сохраняем в сессии сообщение и отправляем редирект на главную страницу.

Как видите, библиотека довольно удобная и работать с ней не сложно. Кроме того, при необходимости с её помощью можно легко добавить возможность регистрации в баг трекере или разделить пользователей на группы с разными правами.

P.S. Если возникли вопросы или есть замечания, пишите, постараюсь ответить 😉