![]() |
![]() |
| http://kurepin.ru/php/slang.ru/12/ |
|
Строим сайт Глава 12. user_access() На очереди у нас user_access(). Прежде чем писать эту функцию, давайте хорошенько поразмыслим над ее задачами. Логическая цепочка проверки уровня доступа к словарю мне видится так: сначала смотрим на user_id. Если он равен нулю, то это обращение незарегистрированного пользователя. В этом случае нам надо проверить только общий доступ к словарю и выдать результат. Если же user_id задан, то необходимо сложить общедоступные права к словарю с правами для указанного пользователя. После этого надо проверить уровень доступа и вернуть разрешение или запрет. А как и где мы опишем права доступа для незарегистрированных пользователей - простых посетителей нашего проекта? Я вижу два варианта: первый - размещать в таблице tbl_user_dic запись с ud_user равным 0, где 0 - все пользователи; или же добавить в таблицу tbl_dic поле d_rights, в котором хранить права доступа для незарегистрированных посетителей сайта. Пользоваться одной таблицей прав - более разумно с точки зрения программирования, но разместить права доступа в tbl_dic вместе с другими данными по словарям - значит ускорить процесс проверки прав для незарегистрированных пользователей, сократив количество таблиц, участвующих в запросе при проверки данных. Я свой выбор остановил на единообразии - решил хранить все права доступа в одной таблице tbl_user_dic. Если же проверка каждого обращения к данным проекта окажется ощутимой тяжестью для сервера - будем оптимизировать анонимные запросы путем кеширования или еще как-нибудь. Пока это вопрос будущего. Итак, давайте сразу в нашу базу данных добавим запись атрибутов доступа для незарегистрированных пользователей: insert into tbl_user_dic(ud_user, ud_dic, ud_rights) values(0,1,1); Вот так, любой анонимный посетитель теперь имеет право на просмотр содержимого нашего первого словаря. Теперь давайте вернемся к механизму записи и проверки атрибутов доступа. Как вы помните, права мы записываем побитно. Правда, я уже не помню, зачем добавил право 8, если есть право 4, его подавляющее (если нельзя совсем удалить описание, то можно его очистить от текста, что приравнивается к удалению), поэтому предлагаю пока заменить 8 на "reserved" - еще пригодится для чего-нибудь более полезного. 00000001 - 1 - просмотр словаря 00000010 - 2 - добавление описания 00000100 - 4 - изменение/удаление описания (чужого) 00001000 - 8 - reserved 00010000 - 16 - добавление слова 00100000 - 32 - удаление слова (чужого) 01000000 - 64 - reserved 10000000 - 128 - контроль доступа Чтобы проверить право доступа, достаточно побитно сложить права пользователя с запрашиваемым правом на совершение действия, воспользовавшись логическим "и". Если вы не сильны в логических операциях, привожу пример: Права пользователя ($user): 00000011 (3) - чтение(1) и добавление описания(2) Запрашиваемое действие ($action): 00000010 - добавление описания (2) Складываем: $access=$user & $action; Побитное "и" вернет нам результат: 00000010. То есть, установленными битами будут только те, которые были установлены в обеих переменных. В этом случае пользователь получает "добро" на совершение операции. Но у нас есть не только права для конкретного пользователя, но и права для всех пользователей, и было бы большой ошибкой - не дать пользователю совершить операцию, разрешенную для всех, но не прописанную специально для него, так как пользователь может разрегистироваться и совершить эту операцию как анонимный пользователь. Поэтому перед проверкой доступа следует сложить права для всех с правами данного пользователя. Для этого лучше всего подходит логическое сложение "или". Немного изменим наш пример: Права для всех ($all): 00000010 (2) - добавление описания Права пользователя ($user): 00000101 (5) - чтение(1) и изменение описания(4) Запрашиваемое действие ($action): 00000010 - добавление описания (2) Накладываем общие права на частные: $user=$all | $user; Теперь права $user равны 00000111. $access=$user & $action; Содержимое $access получилось ненулевым 00000010, а это значит, что доступ пользователю должен быть предоставлен! Поскольку мы не планируем запрашивать несколько атрибутов действий в одном обращении, то после логического "и" мы можем проверить результат как на равенство с запрашиваемым номером атрибута, так и просто проверить на отличность результата от нуля. Для пущей понятности привожу пример "запретного" варианта: $all: 00000001 (1) - чтение $user: 00000011 - чтение и добавление описания $action: 00100000 (32) - добавление слова $all | $user = 00000011 $access = 00000000, так как ни одного бита в правах не совпало с битом, определяющим право на добавление слова. Фуф, по-моему, разжевал эту тему до консистенции детского питания. Давайте теперь запишем проверку доступа в виде функции: highlight_string(' function user_access($dic, $action=1, $user_id=0) { $dic=(int)$dic; $action=(int)$action; $user_id=(int)$user_id; if(!$dic) return(11); // не выбран словарь (не должно такого случаться) if(!$action) return(0); // не запрошено действие (никаких прав не выдано) // запрашиваем публичные права на словарь $err=$this->sql_run(\'select ud_rights from tbl_user_dic whre ud_user=0 && ud_dic=\'.$dic); if($err) return($err); if(!list($all_rights)=mysql_fetch_row($this->sql_res)) return(12); // проверяем общий доступ if($all_rights & $action) return(0); // положительный ответ // проверяем частный доступ, если задан user_id if($user_id) { $err=$this->sql_run(\'select ud_rights from tbl_user_dic whre ud_user=\'.$this->u_id.\' && ud_dic=\'.$dic); if($err) return($err); if(list($user_rights)=mysql_fetch_row($this->sql_res)) { // складываем маски и проверяем доступ if(($user_rights | $all_rights) & $action) return(0); // положительный ответ } } return(1002); // нет прав } ?>');?> По-моему, тут даже объяснять нечего - все сказано в комментариях. Если что-то непонятно - обращайтесь ко мне на . Не забываем записать в errors.txt новые ошибки 11 не выбран словарь - ошибка управления или попытка взлома системы; администратору направлен отчет о произошедшем 12 для данного словаря не определены права общего доступа; администратору отправлено сообщение ... 1002 у вас недостаточно прав для совершения этой операции Продолжим? 12.08.04 |
| реклама на сайте |
|
…
|
| copyright ©2000-2002 Ruslan Kurepin |