Доброго времени суток! Пишу сайт, на котором должны быть следующие категории прав доступа: гость, зарегистрированный пользователь, администраторы (разделение на модераторов не требуется). Гость видит одну меню, зарегистрированный – две, имеет свою страничку, плюс может посылать личные сообщения (ЛС) другим пользователям. Админ может редактировать код страниц. Так же, должна быть страница с новостями сайта. Сейчас: после аутентификации и авторизации (реализовано на sessid, хранящимся в cookies) пользователю выдаётся $chmod (может принимать значения 0, 1 или 2) значения которого хранятся в БД (mysite.users.chmod). Между сессией и любым выводом проверяю этот $chmod и, в зависимости от него, простыми конструкциями if..else определяю какой код выводить пользователю. Вопрос №1: каким образом безопасней всего осуществлять разграничение прав доступа в скрипте? Best practicies? Опыта в этом пока не имею как и действующих сайтов в Сети. Достаточно отдельного поля в БД для уровня доступа (а само разграничение повесить на PHP) или же есть смысл для каждого зарегенного юзверя создавать нового пользователя в БД с определёнными правами на эту самую БД? Вопрос №2: как организовать управление сайтом для администраторов? Из необходимых функций: редактирование страниц сайта (думаю реализовать через простые fopen/flock/fwrite/fclose – не опасно ли это?), создание новых (каким образом?). Вопрос №3: на сайте должна быть страничка с новостями. Их должен добавлять/изменять/удалять администратор. Как строится новостная система? А вывод этой ленты? И, самое главное, как их редактировать? С этой системой всё хуже – не имею никакого даже прототипа, есть одна идея слияния n последних записей страниц из БД, но как это реализовать понятия не имею ): Спасибо. ps: с кодом проблем нет, а вот с алгоритмами вэба пока что совсем беда ):
Через базу делай. После авторизации смотри кто он и выставляй права в сессию. Для админа такая же история, только интереснее, там уже все у него дано о сайте и т.д. Сделай отдельный GET адрес и собери туда себе панель, чтобы работала только после авторизации и с правами именно админа, которые укажешь сам, иначе на адрес нельзя зайти будет (перемещай на главный адрес сайта).
Я сейчас так и делаю: после авторизации айдишник уровня доступа (он же $chmod) пишу в сессию. То бишь, этого механизма достаточно и не стоит заморачиваться, придумывая что-то ещё? Этого уровня безопасности достаточно? Кстати, сейчас на ум пришёл вопрос (добавил так же в шапку): достаточно отдельного поля в БД для уровня доступа (а само разграничение повесить на PHP) или же есть смысл для каждого зарегенного юзверя создавать нового пользователя в БД с определёнными правами на эту самую БД? Собрать GET'ами панель.. Всмысле, для $_GET['edit_page'] открывать редактор, для $_GET['set_chmod'] открывать список юзверей и менять им доступ и так далее? Правильно ли я Вас понял?
Необходимости постоянно инклудить файлы и замарачиваться вообще нет, для этого есть шаблоны. Ну если не понимаете, то пишите как знаете) Я лично не делаю таких приблуд, все намного быстрее и проще. Так и надо к примеру у пользователей в БД access стоит 2 значит админ и ему доступна админ панель по адресу допустим " ?admin=2 " ?admin=2&news=allnews&edit=1 Это просто к примеру. Можно и на сессиях) И через js.
Поясните, пожалуйста, что такое шаблоны? Я понимаю их как include_once('header.php'), include_once('footer.php') и т.д. В том-то и дело – не знаю Поэтому и прошу помощи здесь. Да, суть я так и понял Но не совсем в деталях – зачем передавать уровень доступа в гете? Не безопасней ли писать уровень доступа в сессию и затем его использовать в запросах к БД?
Инфы море в интернете, откройте и почитайте, что такое шаблонизаторы и т.д. Это пример блин. Просто сессия, а инфу ты выведешь прям все в одно место свалишь и сделаешь помойку?) Дело ваше) Мне все равно, вы себе делаете не мне))) Код (PHP): if(!isset($_SESSION['adm'])) { $_SESSION['adm']=0; } $get_admin=isset($_GET['adm']) && $_GET['adm']==2?(int)$_GET['adm']:''; if($get_admin) { if(isset($_SESSION['adm']) && $get_admin===$_SESSION['adm']) { echo'Админ!'; } else { echo'Вам суда нельзя!'; } } Это как пример, а вообще вариантов для админа можно сделать множество)
Намёк ясен, ушёл гуглить А, тогда всё очевидно, у меня сейчас именно так и написано Только в админке пусто. Значит, делаю и думаю в правильном направлении. Спасибо!
шаблон это когда ты собираешь текст в переменную (или юзаешь что-то типа ob_get()) и потом суёшь в шаблон уже.
Проблем я вообще не вижу тут. К примеру я желал когда-то следующее... Была панель авторизации в админку. Допустим admin.php. Авторизацию мог пройти тот у кого chmod>=2. 2-у меня был модератор. 3-был админ, а ниже уже 1-пользователь. 0-гость. -1 забанен. В админке были функции открыты ограничены для модератора. При авторизации разумеется добавляется сессия. Принцип похож как на ipb. Ну а на самом портале все делается через золотю функцию if(). Но я бы на твоем месте не делал открытый URl на ажминку и разные важные файлы. Лучше через аштекст или get
Сессия безопасна. Можно и ими, но тут для удобности лучше конечно сделать в базе access 1,10,100 и проверить только на "1-0". И только тогда сверить когда заходит в админ по адресу какому ему можно ?admin=1,10,100 иначе редирект. Вообще недоступные адреса перемещать. Если дергают постоянно банить и перенаправлять.)
Так же, отдельный совет. Создай отдельный файл с функциями. Допустим у меня было много чего где зависило от уровня пользователя. Форум, панель управления, админка, профиль пользователя. Д.с. Добавления новостей, какие-то редактирования и тд и тп. И не было бы логично постоянно обращаться к базе пользователя и делать запросы на права пользователя. Слишком много писанины.
Есть ли какие-то решения кроме if/switch? Или именно так оно и пишется везде и такая практика – ок? Просто очень лениво в коде видеть простыню из тонны вложенностей друг в друга и хотелось бы её как-то упростить. offtop: В моём конкретном примере вся функциональность админки заключается в "оболочке для нуба" чтобы можно было тексты редактировать на сайте, добавлять новости и менять уровень доступа юзверей поэтому делать функциональную админку буду уже после закрытия всех баг- и фич-реквестов. Простите, пожалуйста, не уследил за мыслью комментария: какие адреса и куда перемещать? Согласен. У меня есть отдельный connDB.php, а так же admheap.php, в котором лежат все нужные классы с методами для админки. А в скрипте просто вызываю через через __autoload() с заранее определённым конструктором.
Не делайте много инклудов в разных местах, их можно подключить все через цикл на одном index. При этом можно будет даже управлять когда и каким по счету вызывать. Облегчив все задачи, все классы и функции подключенные выше, будут доступны в админке: Код (PHP): $config=array( 'rules'=>'1,10,100', 'rules_count'=>3, 'rules_separator'=>',' ); $rule=array(); $rules=explode($config['rules_separator'],$config['rules'],$config['rules_count']); for($i=0;$i<sizeof($rules);++$i) { $rule[$rules[$i]]=$rules[$i]; } $get_admin=isset($_GET['admin'])?$_GET['admin']:''; if(isset($rule[$get_admin])) { define('ADMINKA',true); } else { } if(!defined('ADMINKA')) { } else { }
ну это самый лучший вар ант реализовать через эту функцию, не понимаю чем она тебя не устраивает) единственное, чем ты можешь уменьшить писанину, это создать класс/функцию и при необходимости обращаться к ней. А по поводу перемещения адреса - не увязачка произошла, это не мой пост)
А у меня нет инклудов, кроме трёх: conndb.php, admheap.php и include_once($page), где последний – для загрузки содержимого страницы, от которого скоро тоже откажусь в пользу хранения страниц внутри БД. Все классы подключаются autoload'ом (достаточно, например впервые обратиться к классу myClass::getVal() чтобы файл myClass.php автоматически заинклудился). Я банально не знаю других более простых способов инклуда исходников по требованию. Какие существуют решения более удобные, чем этот? Скрей всего, я сейчас окажусь жутким нубом, но чем данные преобразования выигрышны? Зачем нужен $rule[]? Например, чем Ваш пример типа такого Код (PHP): if(!defined('ADMINKA')) { // нема доступа } else { // бобро пожаловать, админ! } или даже такого Код (PHP): define('CHMOD',1); /* определяем уровень и пишем его сюда в виде 1, 10 или 100 */; switch (CHMOD) { case 1: // админим break; case 10: // модерируем break; // и т.д. } Правильней (или безошибочней, без дыр в безопасности?), чем типа такого Код (PHP): // при выходе чистим сессию if (isset($_GET['logout'])) { unset($_SESSION['username']); unset($_SESSION['chmod']); session_destroy(); header('Location: index.php'); die(); } // Если юзверь авторизован, то выполняем проверку на доступ if ($chmod===$_SESSION['chmod'] AND $chmod===1) { // допуск к дминке } // Если юзверь не залогинен, то при авторизации пишем уровень доступа в сессию // где $user_data содержит в себе результаты запроса к БД // $query = 'SELECT id, password, chmod FROM users WHERE username="'.mysql_real_escape_string($username).'" LIMIT 1;' $chmod = $_SESSION['chmod'] = $user_data['chmod']; У меня нет цели холиварить, просто на мой взгляд эти три способа одинаковы и хочу понять-таки разницу. Большим объёмом кода и уходом исходников далеко вправо ибо имею привычку все вложенности табулировать ради удобства чтения кода. Если нет кардинальных новых приёмов, то так нет, обойдусь и if/switch
Это-то да – для каждого пользователя базы Сейчас у меня один-единственный (не считая root'а) пользователь БД, у которого есть доступ только к базе сайта, а при регистрации пользователя сайта пишется просто новая строка (со полями id, user, hash, chmod, ip) в таблицу users. У меня другой вопрос: есть ли смысл для каждого пользователя сайта создавать пользователя базы? Например, как правильней/лучше/быстрее/удобнее хранить пользовательские данные (аватарки, фотоальбом, информацию о и прочие): в дополнительном поле таблицы users? Создавать новую таблицу для каждого пользователя с полями avatar, pictures, info ...? Или создавать новую базу с такими же таблицами и всего одним полем?
Я вообще делаю иначе... Даже с подключениями классов и т. д., загрузка констант и подобных для удобства наработак. Код (PHP): private static function load_class() { $file='load_class.ini'; if(self::exists(CLASSES.$file)) { ob_start(); foreach(self::get_contents("'".CLASSES.$file."'",true) as $key => $val) { require_once(CLASSES.$val); } return ob_get_clean(); } else { exit('Файл '.str_replace(DIRECTORY,'',CLASSES).'<b style="color:#0000ff;">'.$file.'</b> не найден!'); } } И то если там начать еще, что-то менять там я так понял, там можно собрать, что-то большее)))
нет. я не про базу. я про сайт. Добавлено спустя 37 секунд: все права всех пользователей обычно хранят в одной таблице. ну еще можно ввести понятие групп. и давать права юзеру от его группы. Добавлено спустя 2 минуты 18 секунд: забудь вобще эту идею Добавлено спустя 1 минуту 20 секунд: на текущем проекте я сделал что файлы хранятся в случайных папках (именем в два символа). Сами файлы получают уникальное имя сгенерённое случайно.
Не уловил мысль, если честно ): Поясните, пожалуйста, про какую таблицу прав Вы говорите: mysql.user или somesitedb.users? В первой у меня сейчас один пользователь с полными правами на одну-единственную базу somesitedb (через которого и ведётся вся работа сайта с БД) и root, а во второй столько, сколько зарегилось на сайте. Есть ли смысл (и какой, кроме точности логов) для каждого зарегенного на сайте создавать ещё и пользователя БД? Кстати, группы! Совсем забыл, что можно и так сделать, спасибо Достаточно ли будет создать просто новое числовое поле "group" в somesitedb.users, определяющее тип группы? Решение самое очевидное и первое в голове, а верное ли? Про запись файла (fwrite) понятно. Про удаление тоже (запросом почистить поле пути + unlink в скрипте). Но почему используете рандомные имена директорий и файлов, а не, к примеру, usergroup/userid/filename.abc ? В чём выгода? И ещё один вопрос родился по контексту: каким образом ограничить доступ к файлу для юзверя или группы? Ведь если файл хранится по какому-то пути, а этот адрес выдаёт пхп-скрипт, то как защитить файл от прямого доступа по ссылке в обход скрипта?
блин забудь про идею создавать бд для каждого отдельного юзера. в любых её вариантах. да, только надо будет сделать таблицу, в которой обозначить что могут и что не могут члены этих групп. я читал, сам не проверял, что тормозит если будет много файлов в одной папке даже на современных файловых системах. я добавил два символа, чтобы было по-меньше файлов в каждой папке. когда ты хранишь инфо про файл в БД, то тебе всё равно где он лежит. А чтобы исключить совпадения файловых имён, то вот пожалуйста http://www.php.ru/manual/function.uniqid.html от перебора, угадывания и подглядывания спасает рандомное имя. для проверки прав - отдавать скриптом. viewtopic.php?f=13&t=9221
Спасибо за ответы и простите за долгое отсутствие (менял треснувшую матрицу на ноуте). Понял! А даже если рандомное? Я читал, что с этим может помочь .htaccess, но пока не понял как его написать, чтобы к файлам имел доступ только скрипт, но картинки показывались в браузере в теге img.
Вы писали о том, что для загружаемых юзверем файлов генерируете рандомные имена и рандомные папки из двух символов. А как защитить файл даже при прямой ссылке? Например, чтобы при переходе по прямой "somesite.com/upload/files/somefile.png" была ошибка, но при вставке этой же ссылки из пхп в img src нормально показывалась картинка?
да просто закрыть эту папку где всё это свалено и всё тут. отдавать скриптом. никак. просто делаешь правило что все адреса с /site.ru/files/ идут на твой пхп-скрипт, который уже откуда-то из закрытой от доступа папки раздаёт тем, кому можно то, что требуется.