Реализация механизма разграничения прав доступа к админ-части
Реализация механизма разграничения прав доступа к админ-части
Автор: К.Карпенко
На своей практике веб-разработки я очень часто сталкивался с ситуациями, в которых заказчики ставили конкретную цель, а именно о разделении частей админки относительно доступности тем или иным пользователям. При этом разработка данного модуля велась в контексте расширяемой системы, а то есть с нефиксированым числом модулей, к которым организовуется доступ, ну и, соответственно, неограниченным числом пользователей системы.
Что ж, сама по себе данная тема довольно грузная, и требует определённого времени на анализ и постанувку задачи.
В контексте данной статьи, мы будем вести разработку в контексте некоторой абстрактной информационной системы, со своей инфраструктурой и архитектурой, при этом данная система предоставляет пользователю возможность расширять функционал, а то есть устанавливать новые модули, и соответственно устанавливать права доступа к ним тому либо иному пользователю, зарегистрированному в качестве администратора системы.
Давайте с самого начала обсудим архитектуру модульной системы на выбранной нами псевдо-системе.
Все модули представлены ввиде подключаемых к главному документу (индекс-файлу) вставок. Запрос модуля происходит из строки запроса QUERY_STRING, и название подключаемого модуля передаётся в качестве аргумента act. В некотором месте индекса файла происходит изъятие и обработка данного параметра. После, если у пользователя достаточно прав для доступа к модулю в контексте чтения, происходит проверка существования указанного в строке запроса модуля, и если таковой существует, то происходит его подключение к индекс файлу.
Я не просто так упомянул о "контексте чтения", так как наша системе предполагает существование двух контекстов работы с системой, а именно - чтение и запись. При этом под чтением предполагается непосредственный доступ к модулю и к тем его частям, которые не предполагают внесение изменений в структуру данных в БД. Под записью же предполагается непосредственное внесение изменений в информацию, хранимую в базе данных.
Для воплощения данного механизма мы будет проверять значение переменной строки запроса `do`, которая обрабатывается в самом модуле и носит информацию о том, к какому разделу модуля необходимо предоставить доступ пользовалю.
Значение do буду фиксированными, данная переменная будет принимать следующие значения:
main - главная часть модуля (доступно в контексте чтения)
config - раздел настройки модуля (доступно в контексте записи)
create - произвести некоторые действия, по добавлению информации в БД (доступно в контексте записи)
delete - доступ к разделу, предоставляющему возможности удалить некоторую информацию, в контексте данного модуля (доступно в контексте записи)
edit - доступ к редактированию информации в контексте модуля (доступно в контексте записи)
В целом, этот список можно увеличить, при этом всё зависит лишь только от масштабов проекта и его потребностей в функционале.
Теперь непосредственно о модулях. Кроме физического существования некоторого модуля в контексте файловой системы проекта, модуль так же должен быть добавлен в особую таблицу БД, которая будет содержать информацию о всех существующих модулях в системе. Добавление и изменение данных данной таблицы, обычно, производится непосредственно в контексте модулей, а то есть во время их инсталяции в системе. Однако это уже углубление в принципы посмотроения расширяемых систем, о чём мы как-то в другой раз поговорим, и посему, мы ограничимся ручным обновлением и добавлением данных о модулях.
Так, запись о модуле системы будет содержать следующую информацию: английский идентификатор названия модуля, который будет идентичен значению переменной среды GET - act (относительно него будет производится непосредственно запрос модуля), русский идентификатор модуля, который будет использоватся в списке модулей.
Кроме модулей у нас будут ещё две таблицы, а именно таблица в которой будут хранится данные относительно профилей прав доступа и таблица с информацией о пользователях непосредственно.
Таблица профилей безопасности будет состоять всего из трёх полей - идентификатор профиля (числовое значение идентификатора записи), текстый идентификатор модуля (предназначенный для пользователей), а так же особым образом сформированная текстовая метка, содержащая информацию о правах пользователя, в контексте каждого из модулей.
Что ж, давайте рассмотрим эту особую структуру. Она будет следующей: [ module_indefier : [0 | 1]+ \: [0 | 1]+ \;] *
То есть идёт список из пар: имя модуля ":" права чтения "," права записи ";". При этом данная метка обновляется в момент внесения изменений о правах доступа пользователя к системе. Если в системе появляется информация о модуле, который не вошёл в данную метку, то стоит просто произвести процедуру редактирования, и данные сохранятся автоматически.
Теперь же нам осталось рассмотреть структуру всего одной таблицы БД, и мы сможем принятся за реализацию алгоритмической части, а именно таблицы с информацией о пользователях системы, ведь назначение им прав доступа и является нашей главной задачей.
Я не буду добавлять ничего лишнего в неё, но лишь то, что будет использоватся в контексте темы данной статьи. Таблица пользователей будет содержать следующие поля: идентифицатор пользователя (числовой счётчик), логин, пароль (хеш оригинального пароля), профиль безопасности пользователя (идетификатор группы пользователя, относительно прав в системе), и всё. Мне кажется этой информации нам с вами вполне хватит, для реализации поставленной задачи, а уже все остальные надстройки я предоставляю возможность сделать самим.
Итак, структуру мы обсудили, и, надеюсь, у всех сложилось уже некоторое представление о том, как мы будем реализовывать поставленную в теме статьи задачу. Сейчас я приведу вспомогательный SQL-код таблиц, описанных выше, после чего сразу же перейду к воплощению алгоритма проверки прав доступа пользователя, а так же создания и изменения профилей доступа. После каждого отдельного модуля мы подробно обсудим все вопросы, которые могут возникнуть у читателей.
Таблица `modules`:
CREATE TABLE `modules` (
`id` bigint(20) NOT NULL auto_increment,
`indefier` text collate utf8_unicode_ci NOT NULL,
`title` text collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1
DEFAULT CHARSET=utf8
COLLATE=utf8_unicode_ci;
Таблица `secure_groups`:
CREATE TABLE `secure_groups` (
`id` bigint(20) NOT NULL auto_increment,
`title` text collate utf8_unicode_ci NOT NULL,
`perms` text collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1
DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;
Таблица `users`
CREATE TABLE `users` (
`id` bigint(20) NOT NULL auto_increment,
`login` text collate utf8_unicode_ci NOT NULL,
`passwd` text collate utf8_unicode_ci NOT NULL,
`groupId` int(1) NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1
DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;
Далее описан класс для внедрения функций проверки прав доступа пользователей к модулям системы.
class security extends engine{
var $temp=array();
function getUserId(){
$hash=explode('::',$_COOKIE['site_hash']);
$id=$hash[0];
return $id;
}
Данный класс внедряет функции, предназначенные для воплещения алгоритмического задания, описанного выше. Сейчас мы обсудим каждую функцию отдельно.
Функция secure::getUserId()
Используя данную функцию, мы подразумеваем, что во время авторизации пользователя в системе в переменной среде $_COOKIE была установлена переменная `site_hash`, состоящая из идентификатора пользователя в системе и хеша для проверки аутентичности его в системе. Функция просто изымает значение идентификатора, возращая его значение на выходе.
Функция secure::getUserSecurityAccess($id)
На выходе данная функция возвращает идентификатор профиля безопасности текущего пользователя в системе.
Функция secure::checkUserPermission($module,$act))
Производится запрос к БД, относительно прав пользователя на произведение действий чтения/записи в контексте переданного в качестве параметра модуля.
Осталось лишь описать процедуру формирования переменной в среде $_COOKIE, и тему статьи можно будет считать расскрытой.
Процедура авторизации будет выглядеть ввиде внесения личных данных пользователя (логин и пароль) в специальную форму, после отправки которой произойдёт обработка данных, переданных пользователем, по-методу функции checkAuthData(), и, в случае корректности данных, будет произведено сохранение данных о пользователе ввиде куки записи на период установленный пользователем, либо в отсутствии заданного значение на период по-умолчанию.
Для проверки аутентичности данных хранимых в переменной среде $_COOKIE, мы будем использовать функцию EatCookie(), которая будет производить валидацию данных, возвращая булевый результат проверки (истина - ложь).
Я не привожу форму для отправки, так как это не часть теории программирования, указав лишь идентификаторы полей.
`ulogin` - логин пользователя
`upasswd` - пароль пользователя
`stime` - время сессии, устанавливаемое пользователем (от 1 до 5 часов)
`auth` - имя кнопки отправки
function checkAuthData($info){
$login=rawurlencode($info['ulogin']);
$passwd=rawurlencode($info['upasswd']);
$stime=(rawurlencode(trim($info['stime']))=='')?1:rawurlencode($info['stime']);
$err_code=0;
$result=false;
if(trim($login)==''){
$err_code=1;
}
if(trim($passwd)==''){
$err_code=1;
}
if($err_code){
$result=false;
}else{
$conn_id=mysql_connect('host','user','passwd');
mysql_select_db('database');
$q=mysql_query("SELECT * FROM `users` WHERE passwd='".md5($passwd)."'
AND login='".$login."'",$conn_id);
if($q){
if(@myql_numrows($q)!=0){
$row=mysql_fetch_assoc($q);
if($row['status']=='on'){
$hash=$row['id'].'::'.md5(md5($login).
md5($passwd));
setcookie('site_hash',$hash,$stime*3600*60);
$result=true;
}else{
$result=false;
}
}else{
$result=false;
}
}else{
$result=false;
}
mysql_close($conn_id);
}
return $result;
}
Вот, в целом и всё. Осталось лишь пробовать, экспериментировать, ошибатся и находить решение, что я всецело и оставляю вам.
Надеюсь, что мы скоро встретимся, а для тех кто имеет ко мне вопрос в отношении статьи, да и не только - писать на LoRd1990@gmail.com, либо на mag@tnt43.com.
Кто хочет почитать остальные мои статьи - прошу на http://e-code.tnt43.com.
С уважением Карпенко Кирилл, глава IT-отдела ИНПП.
Опубликовал Kest
November 05 2008 21:33:06 ·
0 Комментариев ·
9960 Прочтений ·
• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •
Комментарии
Нет комментариев.
Добавить комментарий
Рейтинги
Рейтинг доступен только для пользователей.
Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.
Нет данных для оценки.
Гость
Вы не зарегистрированны? Нажмите здесь для регистрации.