За последние 24 часа нас посетили 19284 программиста и 1605 роботов. Сейчас ищут 922 программиста ...

Алгоритмы для систем прав доступа, ЛС и новостей

Тема в разделе "PHP для новичков", создана пользователем TrogWar, 25 окт 2012.

  1. TrogWar

    TrogWar Активный пользователь

    С нами с:
    20 окт 2012
    Сообщения:
    40
    Симпатии:
    0
    Адрес:
    Ленинград
    Доброго времени суток!

    Пишу сайт, на котором должны быть следующие категории прав доступа: гость, зарегистрированный пользователь, администраторы (разделение на модераторов не требуется).
    Гость видит одну меню, зарегистрированный – две, имеет свою страничку, плюс может посылать личные сообщения (ЛС) другим пользователям. Админ может редактировать код страниц.
    Так же, должна быть страница с новостями сайта.

    Сейчас: после аутентификации и авторизации (реализовано на sessid, хранящимся в cookies) пользователю выдаётся $chmod (может принимать значения 0, 1 или 2) значения которого хранятся в БД (mysite.users.chmod). Между сессией и любым выводом проверяю этот $chmod и, в зависимости от него, простыми конструкциями if..else определяю какой код выводить пользователю.

    Вопрос №1: каким образом безопасней всего осуществлять разграничение прав доступа в скрипте? Best practicies? Опыта в этом пока не имею как и действующих сайтов в Сети. Достаточно отдельного поля в БД для уровня доступа (а само разграничение повесить на PHP) или же есть смысл для каждого зарегенного юзверя создавать нового пользователя в БД с определёнными правами на эту самую БД?

    Вопрос №2: как организовать управление сайтом для администраторов?
    Из необходимых функций: редактирование страниц сайта (думаю реализовать через простые fopen/flock/fwrite/fclose – не опасно ли это?), создание новых (каким образом?).

    Вопрос №3: на сайте должна быть страничка с новостями. Их должен добавлять/изменять/удалять администратор. Как строится новостная система? А вывод этой ленты? И, самое главное, как их редактировать?
    С этой системой всё хуже – не имею никакого даже прототипа, есть одна идея слияния n последних записей страниц из БД, но как это реализовать понятия не имею ):

    Спасибо.

    ps: с кодом проблем нет, а вот с алгоритмами вэба пока что совсем беда ):
     
  2. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Через базу делай.
    После авторизации смотри кто он и выставляй права в сессию.

    Для админа такая же история, только интереснее, там уже все у него дано о сайте и т.д.
    Сделай отдельный GET адрес и собери туда себе панель, чтобы работала только после авторизации и с правами именно админа, которые укажешь сам, иначе на адрес нельзя зайти будет (перемещай на главный адрес сайта).
     
  3. TrogWar

    TrogWar Активный пользователь

    С нами с:
    20 окт 2012
    Сообщения:
    40
    Симпатии:
    0
    Адрес:
    Ленинград
    Я сейчас так и делаю: после авторизации айдишник уровня доступа (он же $chmod) пишу в сессию.
    То бишь, этого механизма достаточно и не стоит заморачиваться, придумывая что-то ещё? Этого уровня безопасности достаточно?
    Кстати, сейчас на ум пришёл вопрос (добавил так же в шапку): достаточно отдельного поля в БД для уровня доступа (а само разграничение повесить на PHP) или же есть смысл для каждого зарегенного юзверя создавать нового пользователя в БД с определёнными правами на эту самую БД?

    Собрать GET'ами панель.. Всмысле, для $_GET['edit_page'] открывать редактор, для $_GET['set_chmod'] открывать список юзверей и менять им доступ и так далее? Правильно ли я Вас понял?
     
  4. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Необходимости постоянно инклудить файлы и замарачиваться вообще нет, для этого есть шаблоны.
    Ну если не понимаете, то пишите как знаете)
    Я лично не делаю таких приблуд, все намного быстрее и проще.

    Так и надо к примеру у пользователей в БД access стоит 2 значит админ и ему доступна админ панель по адресу допустим " ?admin=2 "

    ?admin=2&news=allnews&edit=1
    Это просто к примеру.

    Можно и на сессиях)
    И через js.
     
  5. TrogWar

    TrogWar Активный пользователь

    С нами с:
    20 окт 2012
    Сообщения:
    40
    Симпатии:
    0
    Адрес:
    Ленинград
    Поясните, пожалуйста, что такое шаблоны?
    Я понимаю их как include_once('header.php'), include_once('footer.php') и т.д.

    В том-то и дело – не знаю :) Поэтому и прошу помощи здесь.

    Да, суть я так и понял :)
    Но не совсем в деталях – зачем передавать уровень доступа в гете? Не безопасней ли писать уровень доступа в сессию и затем его использовать в запросах к БД?
     
  6. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Инфы море в интернете, откройте и почитайте, что такое шаблонизаторы и т.д.


    Это пример блин.
    Просто сессия, а инфу ты выведешь прям все в одно место свалишь и сделаешь помойку?) Дело ваше)
    Мне все равно, вы себе делаете не мне)))

    Код (PHP):
    1. if(!isset($_SESSION['adm'])) {
    2.     $_SESSION['adm']=0;
    3. }
    4. $get_admin=isset($_GET['adm']) && $_GET['adm']==2?(int)$_GET['adm']:'';
    5. if($get_admin) {
    6.     if(isset($_SESSION['adm']) && $get_admin===$_SESSION['adm']) {
    7.         echo'Админ!';
    8.     } else {
    9.         echo'Вам суда нельзя!';
    10.     }
    11. } 

    Это как пример, а вообще вариантов для админа можно сделать множество)
     
  7. TrogWar

    TrogWar Активный пользователь

    С нами с:
    20 окт 2012
    Сообщения:
    40
    Симпатии:
    0
    Адрес:
    Ленинград
    Намёк ясен, ушёл гуглить :)

    А, тогда всё очевидно, у меня сейчас именно так и написано :) Только в админке пусто. Значит, делаю и думаю в правильном направлении. Спасибо!
     
  8. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    шаблон это когда ты собираешь текст в переменную (или юзаешь что-то типа ob_get()) и потом суёшь в шаблон уже.
     
  9. korih

    korih Активный пользователь

    С нами с:
    12 окт 2011
    Сообщения:
    34
    Симпатии:
    0
    Проблем я вообще не вижу тут. К примеру я желал когда-то следующее... Была панель авторизации в админку. Допустим admin.php. Авторизацию мог пройти тот у кого chmod>=2. 2-у меня был модератор. 3-был админ, а ниже уже 1-пользователь. 0-гость. -1 забанен. В админке были функции открыты ограничены для модератора. При авторизации разумеется добавляется сессия. Принцип похож как на ipb. Ну а на самом портале все делается через золотю функцию if(). Но я бы на твоем месте не делал открытый URl на ажминку и разные важные файлы. Лучше через аштекст или get
     
  10. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Сессия безопасна.
    Можно и ими, но тут для удобности лучше конечно сделать в базе access 1,10,100 и проверить только на "1-0".
    И только тогда сверить когда заходит в админ по адресу какому ему можно ?admin=1,10,100 иначе редирект.
    Вообще недоступные адреса перемещать.
    Если дергают постоянно банить и перенаправлять.)
     
  11. korih

    korih Активный пользователь

    С нами с:
    12 окт 2011
    Сообщения:
    34
    Симпатии:
    0
    Так же, отдельный совет. Создай отдельный файл с функциями. Допустим у меня было много чего где зависило от уровня пользователя. Форум, панель управления, админка, профиль пользователя. Д.с. Добавления новостей, какие-то редактирования и тд и тп. И не было бы логично постоянно обращаться к базе пользователя и делать запросы на права пользователя. Слишком много писанины.
     
  12. TrogWar

    TrogWar Активный пользователь

    С нами с:
    20 окт 2012
    Сообщения:
    40
    Симпатии:
    0
    Адрес:
    Ленинград
    Есть ли какие-то решения кроме if/switch? Или именно так оно и пишется везде и такая практика – ок? :)
    Просто очень лениво в коде видеть простыню из тонны вложенностей друг в друга и хотелось бы её как-то упростить.

    offtop: В моём конкретном примере вся функциональность админки заключается в "оболочке для нуба" чтобы можно было тексты редактировать на сайте, добавлять новости и менять уровень доступа юзверей поэтому делать функциональную админку буду уже после закрытия всех баг- и фич-реквестов.

    Простите, пожалуйста, не уследил за мыслью комментария: какие адреса и куда перемещать?

    Согласен. У меня есть отдельный connDB.php, а так же admheap.php, в котором лежат все нужные классы с методами для админки. А в скрипте просто вызываю через через __autoload() с заранее определённым конструктором.
     
  13. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Не делайте много инклудов в разных местах, их можно подключить все через цикл на одном index.
    При этом можно будет даже управлять когда и каким по счету вызывать.

    Облегчив все задачи, все классы и функции подключенные выше, будут доступны в админке:

    Код (PHP):
    1. $config=array(
    2.     'rules'=>'1,10,100',
    3.     'rules_count'=>3,
    4.     'rules_separator'=>','
    5. );
    6. $rule=array();
    7. $rules=explode($config['rules_separator'],$config['rules'],$config['rules_count']);
    8. for($i=0;$i<sizeof($rules);++$i) {
    9.     $rule[$rules[$i]]=$rules[$i];
    10. }
    11. $get_admin=isset($_GET['admin'])?$_GET['admin']:'';
    12. if(isset($rule[$get_admin])) {
    13.     define('ADMINKA',true);
    14. } else {
    15. }
    16. if(!defined('ADMINKA')) {
    17. } else {
    18. } 
     
  14. korih

    korih Активный пользователь

    С нами с:
    12 окт 2011
    Сообщения:
    34
    Симпатии:
    0
    ну это самый лучший вар ант реализовать через эту функцию, не понимаю чем она тебя не устраивает) единственное, чем ты можешь уменьшить писанину, это создать класс/функцию и при необходимости обращаться к ней. А по поводу перемещения адреса - не увязачка произошла, это не мой пост)
     
  15. TrogWar

    TrogWar Активный пользователь

    С нами с:
    20 окт 2012
    Сообщения:
    40
    Симпатии:
    0
    Адрес:
    Ленинград
    А у меня нет инклудов, кроме трёх: conndb.php, admheap.php и include_once($page), где последний – для загрузки содержимого страницы, от которого скоро тоже откажусь в пользу хранения страниц внутри БД.
    Все классы подключаются autoload'ом (достаточно, например впервые обратиться к классу myClass::getVal() чтобы файл myClass.php автоматически заинклудился).
    Я банально не знаю других более простых способов инклуда исходников по требованию. Какие существуют решения более удобные, чем этот?

    Скрей всего, я сейчас окажусь жутким нубом, но чем данные преобразования выигрышны? Зачем нужен $rule[]?
    Например, чем Ваш пример типа такого
    Код (PHP):
    1. if(!defined('ADMINKA')) {
    2.    // нема доступа
    3. } else {
    4.   // бобро пожаловать, админ!
    5. } 
    6.  
    или даже такого
    Код (PHP):
    1. define('CHMOD',1); /* определяем уровень и пишем его сюда в виде 1, 10 или 100 */;
    2. switch (CHMOD) {
    3.    case 1:
    4.       // админим
    5.       break;
    6.    case 10:
    7.       // модерируем
    8.       break;
    9. // и т.д.
    10. }
    11.  
    Правильней (или безошибочней, без дыр в безопасности?), чем типа такого
    Код (PHP):
    1. // при выходе чистим сессию
    2. if (isset($_GET['logout'])) {
    3.    unset($_SESSION['username']);
    4.    unset($_SESSION['chmod']);
    5.    header('Location: index.php');
    6.    die();
    7. }
    8.  
    9. // Если юзверь авторизован, то выполняем проверку на доступ
    10. if ($chmod===$_SESSION['chmod'] AND $chmod===1) {
    11.    // допуск к дминке
    12. }
    13. // Если юзверь не залогинен, то при авторизации пишем уровень доступа в сессию
    14. // где $user_data содержит в себе результаты запроса к БД
    15. // $query = 'SELECT id, password, chmod FROM users WHERE username="'.mysql_real_escape_string($username).'" LIMIT 1;'
    16. $chmod = $_SESSION['chmod'] = $user_data['chmod'];
    17.  
    У меня нет цели холиварить, просто на мой взгляд эти три способа одинаковы и хочу понять-таки разницу.

    Большим объёмом кода и уходом исходников далеко вправо :) ибо имею привычку все вложенности табулировать ради удобства чтения кода. Если нет кардинальных новых приёмов, то так нет, обойдусь и if/switch :)
     
  16. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    обычно права просто хранятся в таблице прав =)

    Добавлено спустя 18 секунд:
    каждое отдельно
     
  17. TrogWar

    TrogWar Активный пользователь

    С нами с:
    20 окт 2012
    Сообщения:
    40
    Симпатии:
    0
    Адрес:
    Ленинград
    Это-то да – для каждого пользователя базы :)
    Сейчас у меня один-единственный (не считая root'а) пользователь БД, у которого есть доступ только к базе сайта, а при регистрации пользователя сайта пишется просто новая строка (со полями id, user, hash, chmod, ip) в таблицу users.

    У меня другой вопрос: есть ли смысл для каждого пользователя сайта создавать пользователя базы?
    Например, как правильней/лучше/быстрее/удобнее хранить пользовательские данные (аватарки, фотоальбом, информацию о и прочие): в дополнительном поле таблицы users? Создавать новую таблицу для каждого пользователя с полями avatar, pictures, info ...? Или создавать новую базу с такими же таблицами и всего одним полем?
     
  18. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Я вообще делаю иначе...

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

    Код (PHP):
    1. private static function load_class() {
    2.     $file='load_class.ini';
    3.     if(self::exists(CLASSES.$file)) {
    4.         ob_start();
    5.         foreach(self::get_contents("'".CLASSES.$file."'",true) as $key => $val) {
    6.             require_once(CLASSES.$val);
    7.         }
    8.         return ob_get_clean();
    9.     } else {
    10.         exit('Файл '.str_replace(DIRECTORY,'',CLASSES).'<b style="color:#0000ff;">'.$file.'</b> не найден!');
    11.     }
    12. } 
    И то если там начать еще, что-то менять там я так понял, там можно собрать, что-то большее)))
     
  19. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    нет. я не про базу. я про сайт.

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

    Добавлено спустя 2 минуты 18 секунд:
    забудь вобще эту идею

    Добавлено спустя 1 минуту 20 секунд:
    на текущем проекте я сделал что файлы хранятся в случайных папках (именем в два символа). Сами файлы получают уникальное имя сгенерённое случайно.
     
  20. TrogWar

    TrogWar Активный пользователь

    С нами с:
    20 окт 2012
    Сообщения:
    40
    Симпатии:
    0
    Адрес:
    Ленинград
    Не уловил мысль, если честно ): Поясните, пожалуйста, про какую таблицу прав Вы говорите: mysql.user или somesitedb.users?
    В первой у меня сейчас один пользователь с полными правами на одну-единственную базу somesitedb (через которого и ведётся вся работа сайта с БД) и root, а во второй столько, сколько зарегилось на сайте. Есть ли смысл (и какой, кроме точности логов) для каждого зарегенного на сайте создавать ещё и пользователя БД?

    Кстати, группы! Совсем забыл, что можно и так сделать, спасибо :)
    Достаточно ли будет создать просто новое числовое поле "group" в somesitedb.users, определяющее тип группы? Решение самое очевидное и первое в голове, а верное ли?

    Про запись файла (fwrite) понятно. Про удаление тоже (запросом почистить поле пути + unlink в скрипте). Но почему используете рандомные имена директорий и файлов, а не, к примеру, usergroup/userid/filename.abc ? В чём выгода?

    И ещё один вопрос родился по контексту: каким образом ограничить доступ к файлу для юзверя или группы? Ведь если файл хранится по какому-то пути, а этот адрес выдаёт пхп-скрипт, то как защитить файл от прямого доступа по ссылке в обход скрипта?
     
  21. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    блин

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

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

    когда ты хранишь инфо про файл в БД, то тебе всё равно где он лежит. А чтобы исключить совпадения файловых имён, то вот пожалуйста http://www.php.ru/manual/function.uniqid.html

    от перебора, угадывания и подглядывания спасает рандомное имя. для проверки прав - отдавать скриптом. viewtopic.php?f=13&t=9221
     
  22. TrogWar

    TrogWar Активный пользователь

    С нами с:
    20 окт 2012
    Сообщения:
    40
    Симпатии:
    0
    Адрес:
    Ленинград
    Спасибо за ответы и простите за долгое отсутствие (менял треснувшую матрицу на ноуте).

    Понял!

    А даже если рандомное? Я читал, что с этим может помочь .htaccess, но пока не понял как его написать, чтобы к файлам имел доступ только скрипт, но картинки показывались в браузере в теге img.
     
  23. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    не понял. расскажи ещё раз, перечитывать лень =)
     
  24. TrogWar

    TrogWar Активный пользователь

    С нами с:
    20 окт 2012
    Сообщения:
    40
    Симпатии:
    0
    Адрес:
    Ленинград
    Вы писали о том, что для загружаемых юзверем файлов генерируете рандомные имена и рандомные папки из двух символов.
    А как защитить файл даже при прямой ссылке? Например, чтобы при переходе по прямой "somesite.com/upload/files/somefile.png" была ошибка, но при вставке этой же ссылки из пхп в img src нормально показывалась картинка?
     
  25. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    да просто закрыть эту папку где всё это свалено и всё тут.

    отдавать скриптом.
    никак. просто делаешь правило что все адреса с /site.ru/files/ идут на твой пхп-скрипт, который уже откуда-то из закрытой от доступа папки раздаёт тем, кому можно то, что требуется.