За последние 24 часа нас посетили 17580 программистов и 1720 роботов. Сейчас ищут 1842 программиста ...

Мой первый сайт на PHP

Тема в разделе "PHP для новичков", создана пользователем Dimon2x, 29 май 2017.

  1. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    Оцените, мой небольшой сервис вопросов и ответов, всё делал сам, на чистом html, css, js и php.

    Очень интересно узнать, удобно ли я сделал админку?

    Для входа в админку, надо указать GET параметр ?admin=1 и ввести admin и admin

    только не удаляйте разделы, которые вы не создавали.

    http://phpkurs.16mb.com/?admin=1

    сам сайт http://phpkurs.16mb.com/

    весь код на гитхабе https://github.com/Div-Man/faq в коде получилось, очень много дублирования.

    Описание клиентской части
    • Пользователи могут просматривать категории, вопросы и ответы.
    • Любой пользователь может задать вопрос, указав своё имя, адрес электронной почты, выбрав категорию и написав текст вопроса.
    • Вопросы без ответов не публикуются на сайте.
    Вход в интерфейс администратора
    • Для попадания в интерфейс администратора нужно ввести логин и пароль.
    • По умолчанию создан единственный администратор с логином admin и паролем admin.
    Возможности в интерфейсе администратора
    • Просматривать список администраторов.
    • Создавать новых администраторов.
    • Изменять пароли существующих администраторов.
    • Удалять существующих администраторов.
    • Просматривать список тем. По каждой теме в списке видно сколько всего вопросов в ней, сколько опубликовано, сколько без ответов.
    • Создавать новые темы.
    • Удалять существующие темы и все вопросы в них.
    • Просматривать вопросы в каждой теме. По каждому вопросу видно дату создания, статус (ожидает ответа / опубликован / скрыт).
    • Удалять любой вопрос из темы.
    • Скрывать опубликованные вопросы.
    • Публиковать скрытые вопросы.
    • Редактировать автора, текст вопроса и текст ответа.
    • Перемещать вопрос из одной темы в другую.
    • Добавлять ответ на вопрос с публикацией на сайте, либо со скрытием вопроса.
    • Видеть список всех вопросов без ответа во всех темах в порядке их добавления. И иметь возможность их редактировать и удалять.
     
    Dmitriy A. Arteshuk нравится это.
  2. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.984
    Симпатии:
    759
    К сожалению, никто не разделит твоей радости. Поверь моему опыту :)
    Если тебе нравится, то продолжай творить.
     
  3. alexblack

    alexblack Старожил

    С нами с:
    20 янв 2016
    Сообщения:
    640
    Симпатии:
    381
    Я подробно не смотрел,но Full Path Disclosure лучше пофиксить
    Fatal error: Call to a member function setFetchMode() on boolean in /home/u293596888/public_html/model/faq.php on line 178
     
  4. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    А вот не надо. Я всегда на стороне упорных новичков, которые что-то пытаются делать.

    Автор, что-то в админке не работает кнопка "ответить".
    Ну и CSS надо все же получше подучить, подпричесать все это дело. Дихайн ну очень сильно хромает пока что. Функциональность же простенькая, да. Но для начала неплохо.
     
  5. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.984
    Симпатии:
    759
    Та же фигня.

    Просто помню свой восторг, когда клепал что-то подобное, и оно работало.
    Но тут такое дело, что компетентным людям видится говнокод, а некомпетентным видится невзрачное рукоделие.
    И ни кто не порадуется с тобой. Вся радость достанется только тебе :)

    А так, я полностью на стороне ТС.
     
  6. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    @Dimon2x
    слушай, неплохо.
     
  7. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    Вот тебе небольшое ревью по коду:

    1)
    PHP:
    1. die('Database error: '.$e->getMessage().'<br>');
    Не надо так делать. Незачем на пользователя это вываливать. Пиши это в лог себе. А пользователю просто покажи нейтральную надпись. мол, так и так, неполадки, так и так, исправим.

    2) После таких вещей, то бишь переадресации
    PHP:
    1. if(!empty($_SESSION['user'])){
    2.             header('Location: ?interface-admin=1');
    3.         }
    Обычно сразу можно дергать die или exit. Ты уже выкинул заголовок переадресации. Все остальное, что может выдать сервер, уже никому не нужно стало. Этот запрос объявлен закрытым.

    3)
    PHP:
    1. $user = "SELECT `login`, `password` FROM users WHERE login = '" . $login ."' AND password = '". $password ."'";
    2.  
    3.         $resUser = $this->db->prepare($user);
    4.         $resUser->execute();
    Ты неправильно используешь prepare. У тебя код уязвим к SQL_инъекции. Читай-вникай. Недостаточно просто собрать строку запроса и сделать prepare. Для машины это просто строка текста. Что в ней подготавливать? По каким правилам? Как она разберется, чего ты от нее хочешь? Там все не просто так. Ну и да, по традиции, подумай, нужен ли тебе PDO как таковой.

    4)
    PHP:
    1. function getListAdmin() {
    2.         $sql = "SELECT login, password, id FROM users";
    3.         $allUser = $this->db->query($sql);
    4.         $allUser->setFetchMode(PDO::FETCH_ASSOC);
    5.         return $allUser->fetchAll();
    6.     }
    Полные выборки лучше не делать. Думай сразу наперед. Что будешь делать, когда будет миллион пользователей? То-то и оно. Лимиты. Условия. Это вот все надо применять сразу.

    5)
    PHP:
    1. $login = strip_tags(trim($l));
    2.         $password = strip_tags(trim($p));
    Не надо так делать. Это порча данных. Во-первых, ник человека будет не тот, какой он ввел. А это его личное дело, в общем-то. Не хочешь, чтобы его ник сломал верстку - просто при выводе данных прогоняй их через htmlspecialchars();
    Во-вторых, как думаешь, что случится с крайне сильным паролем H<DSу2128dfHDGQUWD@^%#R&*&)0r9y32ufdq3>76 после функции strip_tags? Он превратится в H76. Это не круто. Ты подставил пользователя. Да и какая разница, что он там в пароле написал? Чем тебе там угловые скобки не угодили?

    6)
    Ты не хэшируешь пароли и хранишь их в открытом виде. Это неправильно. Так делать нельзя. Как минимум - это не этично. Как максимум - не безопасно. Люди, регаясь у тебя, доверяют тебе свой пароль - это очень ценная вещь. Твоя святая обязанность - защитить его от утечки наружу. И, в первую очередь, оградить себя/своих админов от соблазна их использования. Пользователь доверяет тебе. Соответствуй. Читай вникай.

    7)
    PHP:
    1. $input_name = trim(htmlspecialchars(strip_tags($name)));
    Почитай в отдельности про каждую функцию. И подумай, почему эта конструкция - бред. Да да, ты ее подглядел где-то в интернете/видеокурсах/на каком-то форуме. Но это не отменяет того факта, что это бред. Эта конструкция гуляет по интернетам и уже стала своего рода лакмусовой бумажкой. И она у тебя повсюду. Знаешь, что самое забавное? Она не дает вообще никакой защиты. Корёжит входящие данные, подменяет в них символы, увеличивая вес данных, но никак не делает их безопасными для вставки в БД.

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

    8)
    При этом ты пользуешься "коробочной" фильтрацией для емейла. Молодец. Это правильно. Не стал городить огороды из двадцатиэтажных регулярок.

    9)
    У тебя в all-question.php(и еще в ряде файлов, отвечающих за генерацию view) есть целая микробиблиотека на JS. Почему бы не вынести все это в отдельный файл? Увеличишь скорость загрузки сайта.

    10)Здесь и далее
    PHP:
    1. <a href="?interface-admin=1&del-id='.$admin['id'].'">Удалить</a>'
    Подобные конструкции - это CSRF-уязвимость. Я могу прям вот тут в тело этого сообщения закинуть картинку, у которой src будет равен запросу определенному. Ты, просто открыв сообщение на этом форуме, просто вот увидев это сообщение, сам того не подозревая выполнишь то, что я прописал в ссылке. Браузер отправит запрос на сайт, и, если ты там залогинен с правами администратора, запрос отработает в штатном режиме, как если бы ты сам руками нажал на нужную кнопку. Как пример, с использованием цитируемого кода я могу твоими руками удалить чужую учетную запись.

    --------------------------

    На первый взгляд это вот то, что бросилось в глаза.
    Глубже ревьювить нет времени, не обессудь.

    Проблемы, описанные выше - типичные для начинающих разработчиков. Это норма поначалу. Почитай материалы по ссылкам, погугли то, что недопонял, исправь, вот ты и вырос чуток над самим собой, а это здорово :)

    Главное руки не опускать.

    При этом код, что интересно, написан аккуратно, с определенной логикой, читабельностью и понятностью. Ты в PHP пришел с другого языка?
     
    Dimon2x и mahmuzar нравится это.
  8. _ne_scaju_

    _ne_scaju_ Старожил

    С нами с:
    25 ноя 2016
    Сообщения:
    2.149
    Симпатии:
    118
    @Fell-x27
    Вот мне стало интересно он пишет запрос на вывод данных такой:
    PHP:
    1. $user = "SELECT `login`, `password` FROM users WHERE login = '" . $login ."' AND password = '". $password ."'";
    2. $resUser = $this->db->prepare($user);
    3. $resUser->execute();
    и ты говоришь что он подвержен инъекциям...
    А если записать так, какой из этих запросов не подвержен инъекциям?
    PHP:
    1. $user = "SELECT `login`, `password` FROM users WHERE login = ? AND password = ?";
    2. $resUser = $this->db->prepare($user);
    3. $resUser->execute([$login, $password]);
    Или же так:
    PHP:
    1. $user = "SELECT `login`, `password` FROM users WHERE login =  :login AND password = :password";
    2. $resUser = $this->db->prepare($user);
    3. $resUser -> bindValue(:login, $login);
    4. $resUser -> bindValue(:login, $password);
    5. $resUser->execute();
    Безопасны ли такие запросы? Вот именно меня интересует, плейсхолдеры использовать лучше, или же при выполнении в execute подставлять данные которые передаем, как правильней и защищенней будет от инъекций? Я лично сейчас практикую первый запрос...
     
    #8 _ne_scaju_, 29 май 2017
    Последнее редактирование: 30 май 2017
  9. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.583
    Симпатии:
    1.761
    Что я такого могу сделать на своём сайте, имея пароль пользователя, чего не могу сделать, не имея его? Разве что попытать счастья и взломать почту пользователя, надеясь, что он везде ставит один пароль. Утечка - да, а вот защищать от себя - я и так имею доступ ко всему, что пользователь ввёл, обычно
     
  10. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Можно сделать безопасным запрос разными способами.
    Вопрос не в том, какой запрос безопасен с каким подходом.
    Важно понять, при каких условиях запрос становится безопасным или опасным. Тогда ответ будет тебе очевиден.

    Раз ты спрашивает, значит не понимаешь. Спроси, что не понимаешь или проверь своё понимание. Плейсхолдеры тоже могут быть опасными.

    И кавычки забыл на 3 и 4 строке последнего варианта.
     
  11. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.583
    Симпатии:
    1.761
    В плане защиты от данных, ломающих запрос (а именно этим являются SQL-инъекции) именованные и неименованные плейсхолдеры одинаковы.
    --- Добавлено ---
    ТС, если ты уж пишешь MVC, то модель не должна ничего редиректить, выводить какие-то сообщения, заниматься чем-то, кроме работы с данными. Классы не разбиты по сущностям, бесконечные, делают слишком много работы. Аутентификация - это одно, вывод вопросов - это другое. Тоже и с моделью. Админка и фронт в одном классе контроллера - это уже вообще ни о чём.
     
  12. _ne_scaju_

    _ne_scaju_ Старожил

    С нами с:
    25 ноя 2016
    Сообщения:
    2.149
    Симпатии:
    118
    @mkramer
    Я так понял что первый что второй вариант одинаковые?
    @igordata
    Использовать использую но не понимаю, как лучше писать: плесхолдеры или же в execute подставлять данные?
    А то я в execute сейчас данные подставляю, а потом окажется лучше так делать не нужно, и все переделывать придется(...
    --- Добавлено ---
    @mkramer
    Ты кому пишешь сейчас за админку и контроллер?
     
  13. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    В 95% случаев так оно и есть. А там можно и до финансов добраться, если клиент не очень любит двухфакторные методы аутентификации.
     
  14. _ne_scaju_

    _ne_scaju_ Старожил

    С нами с:
    25 ноя 2016
    Сообщения:
    2.149
    Симпатии:
    118
    @Fell-x27
    а что на счет моего заданного вопроса?
     
  15. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    Прежде чем архитектурой заниматься, надо научиться азам. По архитектуре как таковой я, как видишь, ни слова не сказал парню. Есть проблемы более насущные и менее абстрактные. Архитектура - это свой головняк. Проблемы безопасности - чужой. Чужой приоритетнее.

    А на него тебе уже ответили.

    Но вот Игорь туманно намекнул на то, что и подготовленные выражения могут быть опасными, а раскрыть мысль забыл. Речь шла об инъекциях второго порядка. Это атаки через кодировки, или через доверие разработчика к данным, взятым из своей же БД. То есть на кавычках экранированных проблемы не кончаются. Это лишь один из факторов. Самый часто используемый, да, но не единственный.
     
  16. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    @_ne_scaju_
    почитай про инъекции в википедии, потом про PDO и плейсхолдеры и всё такое. Подумай. Потом задай вопрос =) Я буду рад ответить.
     
  17. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    --- Добавлено ---
    А у меня, эта кнопка работает
     
  18. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.583
    Симпатии:
    1.761
    Согласен. Просто раз уж человек называет свои классы "Модель", "Контроллер", то из этого следует, что он что-то где-то об этом прочёл (слышал), что типа "круто". А значит не мешает подсказать, как это делать правильнее
    --- Добавлено ---
    Тебе обязательно переспросить надо то, на что и так очень ясно ответили. Ещё раз, дал ты имена плейсхолдерам (типа :login) или не дал (оставил просто ?), на безопасность запросов не влияет. Другое дело, что именованные удобнее для программиста
     
  19. _ne_scaju_

    _ne_scaju_ Старожил

    С нами с:
    25 ноя 2016
    Сообщения:
    2.149
    Симпатии:
    118
    @mkramer
    Спасибо.
    Только чем они удобней для программиста? Они же увеличивают код, а не именованные, уменьшают. Да и плюс не именованные им важен порядок переменных, а именованным не важен порядок.
     
    #19 _ne_scaju_, 30 май 2017
    Последнее редактирование: 30 май 2017
  20. _ne_scaju_

    _ne_scaju_ Старожил

    С нами с:
    25 ноя 2016
    Сообщения:
    2.149
    Симпатии:
    118
    @igordata
    К тебе у меня особый вопрос, сейчас при выполнении запроса, пробую сделать так:
    PHP:
    1. $send1->execute(array('text' => $message, 'for_user_id' => $for_user_id, 'from_user_id' => $user_id, 'date' => $date, 'pm_read' => 'no', 'folder' => 'inbox', 'history_user_id' => $user_id));
    или так:
    PHP:
    1. $send1->execute(['text' => $message, 'for_user_id' => $for_user_id, 'from_user_id' => $user_id, 'date' => $date, 'pm_read' => 'no', 'folder' => 'inbox', 'history_user_id' => $user_id]);
    Какой вариант лучше использовать, там где ты указываешь array или просто [ ] скобки указывать?
    И как можно узнать при таких условиях какой запрос выполнится быстрее, или же одинаково они выполнятся будут, по времени?
     
  21. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    Я же сделал выборку только админов, а не всех пользователей, просто в таблице users, содержатся только админы, других пользователе, вообще не будет.

    Мне дали заготовку MVC шаблона и я его заполнял.

    До этого учил только JS.
     
  22. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.583
    Симпатии:
    1.761
    Если php >= 5.4, то только квадратные скобки. Вариант с array () был единственным в более ранних версиях. На скорость никак не влияет
     
    _ne_scaju_ нравится это.
  23. _ne_scaju_

    _ne_scaju_ Старожил

    С нами с:
    25 ноя 2016
    Сообщения:
    2.149
    Симпатии:
    118
    @mkramer
    Понятно, и еще раз спасибо.
    А на счет раннего вопроса ответ будет?
    Почему программисты выбирают именно именованные плейсхолдеры?
     
  24. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.583
    Симпатии:
    1.761
    Лучше читаются именованные. И удобнее выражения подставлять. А вообще, на вкус и цвет
     
  25. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.770
    Адрес:
    :сердА
    Нормальные имена переменных тоже увеличивают код. И они удобнее для программиста. Не в краткости кода счастье и удобство.