Оцените, мой небольшой сервис вопросов и ответов, всё делал сам, на чистом 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. Возможности в интерфейсе администратора Просматривать список администраторов. Создавать новых администраторов. Изменять пароли существующих администраторов. Удалять существующих администраторов. Просматривать список тем. По каждой теме в списке видно сколько всего вопросов в ней, сколько опубликовано, сколько без ответов. Создавать новые темы. Удалять существующие темы и все вопросы в них. Просматривать вопросы в каждой теме. По каждому вопросу видно дату создания, статус (ожидает ответа / опубликован / скрыт). Удалять любой вопрос из темы. Скрывать опубликованные вопросы. Публиковать скрытые вопросы. Редактировать автора, текст вопроса и текст ответа. Перемещать вопрос из одной темы в другую. Добавлять ответ на вопрос с публикацией на сайте, либо со скрытием вопроса. Видеть список всех вопросов без ответа во всех темах в порядке их добавления. И иметь возможность их редактировать и удалять.
К сожалению, никто не разделит твоей радости. Поверь моему опыту Если тебе нравится, то продолжай творить.
Я подробно не смотрел,но Full Path Disclosure лучше пофиксить Fatal error: Call to a member function setFetchMode() on boolean in /home/u293596888/public_html/model/faq.php on line 178
А вот не надо. Я всегда на стороне упорных новичков, которые что-то пытаются делать. Автор, что-то в админке не работает кнопка "ответить". Ну и CSS надо все же получше подучить, подпричесать все это дело. Дихайн ну очень сильно хромает пока что. Функциональность же простенькая, да. Но для начала неплохо.
Та же фигня. Просто помню свой восторг, когда клепал что-то подобное, и оно работало. Но тут такое дело, что компетентным людям видится говнокод, а некомпетентным видится невзрачное рукоделие. И ни кто не порадуется с тобой. Вся радость достанется только тебе А так, я полностью на стороне ТС.
Вот тебе небольшое ревью по коду: 1) PHP: die('Database error: '.$e->getMessage().'<br>'); Не надо так делать. Незачем на пользователя это вываливать. Пиши это в лог себе. А пользователю просто покажи нейтральную надпись. мол, так и так, неполадки, так и так, исправим. 2) После таких вещей, то бишь переадресации PHP: if(!empty($_SESSION['user'])){ header('Location: ?interface-admin=1'); } Обычно сразу можно дергать die или exit. Ты уже выкинул заголовок переадресации. Все остальное, что может выдать сервер, уже никому не нужно стало. Этот запрос объявлен закрытым. 3) PHP: $user = "SELECT `login`, `password` FROM users WHERE login = '" . $login ."' AND password = '". $password ."'"; $resUser = $this->db->prepare($user); $resUser->execute(); Ты неправильно используешь prepare. У тебя код уязвим к SQL_инъекции. Читай-вникай. Недостаточно просто собрать строку запроса и сделать prepare. Для машины это просто строка текста. Что в ней подготавливать? По каким правилам? Как она разберется, чего ты от нее хочешь? Там все не просто так. Ну и да, по традиции, подумай, нужен ли тебе PDO как таковой. 4) PHP: function getListAdmin() { $sql = "SELECT login, password, id FROM users"; $allUser = $this->db->query($sql); $allUser->setFetchMode(PDO::FETCH_ASSOC); return $allUser->fetchAll(); } Полные выборки лучше не делать. Думай сразу наперед. Что будешь делать, когда будет миллион пользователей? То-то и оно. Лимиты. Условия. Это вот все надо применять сразу. 5) PHP: $login = strip_tags(trim($l)); $password = strip_tags(trim($p)); Не надо так делать. Это порча данных. Во-первых, ник человека будет не тот, какой он ввел. А это его личное дело, в общем-то. Не хочешь, чтобы его ник сломал верстку - просто при выводе данных прогоняй их через htmlspecialchars(); Во-вторых, как думаешь, что случится с крайне сильным паролем H<DSу2128dfHDGQUWD@^%#R&*&)0r9y32ufdq3>76 после функции strip_tags? Он превратится в H76. Это не круто. Ты подставил пользователя. Да и какая разница, что он там в пароле написал? Чем тебе там угловые скобки не угодили? 6) Ты не хэшируешь пароли и хранишь их в открытом виде. Это неправильно. Так делать нельзя. Как минимум - это не этично. Как максимум - не безопасно. Люди, регаясь у тебя, доверяют тебе свой пароль - это очень ценная вещь. Твоя святая обязанность - защитить его от утечки наружу. И, в первую очередь, оградить себя/своих админов от соблазна их использования. Пользователь доверяет тебе. Соответствуй. Читай вникай. 7) PHP: $input_name = trim(htmlspecialchars(strip_tags($name))); Почитай в отдельности про каждую функцию. И подумай, почему эта конструкция - бред. Да да, ты ее подглядел где-то в интернете/видеокурсах/на каком-то форуме. Но это не отменяет того факта, что это бред. Эта конструкция гуляет по интернетам и уже стала своего рода лакмусовой бумажкой. И она у тебя повсюду. Знаешь, что самое забавное? Она не дает вообще никакой защиты. Корёжит входящие данные, подменяет в них символы, увеличивая вес данных, но никак не делает их безопасными для вставки в БД. И опять же, strip_tags - вандальная функция. Она варварски портит данные лишь на основании наличия в них угловых скобок. Никогда ей не пользуйся. Вот прям буквально вот никогда. Вообще. Вообще никогда. 8) При этом ты пользуешься "коробочной" фильтрацией для емейла. Молодец. Это правильно. Не стал городить огороды из двадцатиэтажных регулярок. 9) У тебя в all-question.php(и еще в ряде файлов, отвечающих за генерацию view) есть целая микробиблиотека на JS. Почему бы не вынести все это в отдельный файл? Увеличишь скорость загрузки сайта. 10)Здесь и далее PHP: <a href="?interface-admin=1&del-id='.$admin['id'].'">Удалить</a>' Подобные конструкции - это CSRF-уязвимость. Я могу прям вот тут в тело этого сообщения закинуть картинку, у которой src будет равен запросу определенному. Ты, просто открыв сообщение на этом форуме, просто вот увидев это сообщение, сам того не подозревая выполнишь то, что я прописал в ссылке. Браузер отправит запрос на сайт, и, если ты там залогинен с правами администратора, запрос отработает в штатном режиме, как если бы ты сам руками нажал на нужную кнопку. Как пример, с использованием цитируемого кода я могу твоими руками удалить чужую учетную запись. -------------------------- На первый взгляд это вот то, что бросилось в глаза. Глубже ревьювить нет времени, не обессудь. Проблемы, описанные выше - типичные для начинающих разработчиков. Это норма поначалу. Почитай материалы по ссылкам, погугли то, что недопонял, исправь, вот ты и вырос чуток над самим собой, а это здорово Главное руки не опускать. При этом код, что интересно, написан аккуратно, с определенной логикой, читабельностью и понятностью. Ты в PHP пришел с другого языка?
@Fell-x27 Вот мне стало интересно он пишет запрос на вывод данных такой: PHP: $user = "SELECT `login`, `password` FROM users WHERE login = '" . $login ."' AND password = '". $password ."'"; $resUser = $this->db->prepare($user); $resUser->execute(); и ты говоришь что он подвержен инъекциям... А если записать так, какой из этих запросов не подвержен инъекциям? PHP: $user = "SELECT `login`, `password` FROM users WHERE login = ? AND password = ?"; $resUser = $this->db->prepare($user); $resUser->execute([$login, $password]); Или же так: PHP: $user = "SELECT `login`, `password` FROM users WHERE login = :login AND password = :password"; $resUser = $this->db->prepare($user); $resUser -> bindValue(:login, $login); $resUser -> bindValue(:login, $password); $resUser->execute(); Безопасны ли такие запросы? Вот именно меня интересует, плейсхолдеры использовать лучше, или же при выполнении в execute подставлять данные которые передаем, как правильней и защищенней будет от инъекций? Я лично сейчас практикую первый запрос...
Что я такого могу сделать на своём сайте, имея пароль пользователя, чего не могу сделать, не имея его? Разве что попытать счастья и взломать почту пользователя, надеясь, что он везде ставит один пароль. Утечка - да, а вот защищать от себя - я и так имею доступ ко всему, что пользователь ввёл, обычно
Можно сделать безопасным запрос разными способами. Вопрос не в том, какой запрос безопасен с каким подходом. Важно понять, при каких условиях запрос становится безопасным или опасным. Тогда ответ будет тебе очевиден. Раз ты спрашивает, значит не понимаешь. Спроси, что не понимаешь или проверь своё понимание. Плейсхолдеры тоже могут быть опасными. И кавычки забыл на 3 и 4 строке последнего варианта.
В плане защиты от данных, ломающих запрос (а именно этим являются SQL-инъекции) именованные и неименованные плейсхолдеры одинаковы. --- Добавлено --- ТС, если ты уж пишешь MVC, то модель не должна ничего редиректить, выводить какие-то сообщения, заниматься чем-то, кроме работы с данными. Классы не разбиты по сущностям, бесконечные, делают слишком много работы. Аутентификация - это одно, вывод вопросов - это другое. Тоже и с моделью. Админка и фронт в одном классе контроллера - это уже вообще ни о чём.
@mkramer Я так понял что первый что второй вариант одинаковые? @igordata Использовать использую но не понимаю, как лучше писать: плесхолдеры или же в execute подставлять данные? А то я в execute сейчас данные подставляю, а потом окажется лучше так делать не нужно, и все переделывать придется(... --- Добавлено --- @mkramer Ты кому пишешь сейчас за админку и контроллер?
В 95% случаев так оно и есть. А там можно и до финансов добраться, если клиент не очень любит двухфакторные методы аутентификации.
Прежде чем архитектурой заниматься, надо научиться азам. По архитектуре как таковой я, как видишь, ни слова не сказал парню. Есть проблемы более насущные и менее абстрактные. Архитектура - это свой головняк. Проблемы безопасности - чужой. Чужой приоритетнее. А на него тебе уже ответили. Но вот Игорь туманно намекнул на то, что и подготовленные выражения могут быть опасными, а раскрыть мысль забыл. Речь шла об инъекциях второго порядка. Это атаки через кодировки, или через доверие разработчика к данным, взятым из своей же БД. То есть на кавычках экранированных проблемы не кончаются. Это лишь один из факторов. Самый часто используемый, да, но не единственный.
@_ne_scaju_ почитай про инъекции в википедии, потом про PDO и плейсхолдеры и всё такое. Подумай. Потом задай вопрос =) Я буду рад ответить.
Согласен. Просто раз уж человек называет свои классы "Модель", "Контроллер", то из этого следует, что он что-то где-то об этом прочёл (слышал), что типа "круто". А значит не мешает подсказать, как это делать правильнее --- Добавлено --- Тебе обязательно переспросить надо то, на что и так очень ясно ответили. Ещё раз, дал ты имена плейсхолдерам (типа :login) или не дал (оставил просто ?), на безопасность запросов не влияет. Другое дело, что именованные удобнее для программиста
@mkramer Спасибо. Только чем они удобней для программиста? Они же увеличивают код, а не именованные, уменьшают. Да и плюс не именованные им важен порядок переменных, а именованным не важен порядок.
@igordata К тебе у меня особый вопрос, сейчас при выполнении запроса, пробую сделать так: PHP: $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: $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 или просто [ ] скобки указывать? И как можно узнать при таких условиях какой запрос выполнится быстрее, или же одинаково они выполнятся будут, по времени?
Я же сделал выборку только админов, а не всех пользователей, просто в таблице users, содержатся только админы, других пользователе, вообще не будет. Мне дали заготовку MVC шаблона и я его заполнял. До этого учил только JS.
Если php >= 5.4, то только квадратные скобки. Вариант с array () был единственным в более ранних версиях. На скорость никак не влияет
@mkramer Понятно, и еще раз спасибо. А на счет раннего вопроса ответ будет? Почему программисты выбирают именно именованные плейсхолдеры?
Нормальные имена переменных тоже увеличивают код. И они удобнее для программиста. Не в краткости кода счастье и удобство.