Этот код опасен, вы не должны использовать его в его текущем состоянии.
- Он слепо доверяет
$_COOKIE
и создает запросы SQL, используя конкатенацию строк, без правильного экранирования ввода. Вредоносные пользователи могут легко выполнить SQL-инъекцию в любом приложении, использующем этот класс.
- Наличие ключевого слова
var
, наличие конструктора, использующего то же имя, что и у класса, и отсутствие ключевых слов управления доступом перед методами говорит о том, что код был написан для PHP4, а не PHP5. Это все еще будет работать, хотя
Обе эти проблемы решаемы. Сначала давайте ответим на ваши вопросы.
- Код, написанный @Delan Azabani, является хорошим примером использования класса.
- Код сбивает с толку. Сначала кажется, что код использует объект базы данных real вместо старых низкоуровневых функций, предоставляемых расширением
mysql
. Но затем он идет и вызывает функции из расширения mysql
! Вероятно, это чья-то заказная оболочка. На самом деле код не создает объект базы данных, он просто ссылается на значение $db
в глобальной области видимости, как вы подозреваете.
Вы упомянули, что используете расширение mysql
. Я призываю вас пересмотреть и использовать вместо него PDO или mysqli . Мало того, что этот класс будет работать с обоими (хотя с некоторыми изменениями, чтобы уменьшить явную дыру в безопасности), но ваш собственный код будет лучше использовать более современные, более безопасные методы, используемые в PDO
и mysqli
.
Давайте исправим метод login
, используя PDO.
public function login($username, $password) {
global $db;
$sth = $db->prepare("SELECT user_id FROM users WHERE username = ? AND password = ?");
$sth->execute(array($username, $password));
if($sth->rowCount() == 1) {
$this->user_id = $sth->fetchColumn();
...
Давайте рассмотрим, что изменилось. Сначала мы добавили заполнители запросов , это вопросительные знаки. Метод prepare
возвращает дескриптор оператора , с которым вы, вероятно, уже знакомы. Далее мы сообщаем подготовленному оператору, что он запускается сам, используя метод execute
, передавая массив переменных. Переменные будут автоматически экранированными для вас и затем вставлены в запрос вместо заполнителей.
После выполнения запроса мы используем rowCount
, чтобы получить количество совпадающих строк. Мы хотим ровно одного. Поскольку мы вытягиваем первый столбец первой строки, мы используем fetchColumn , чтобы получить только этот бит данных.
Остальная часть метода входа в систему в порядке.
Метод check
требует аналогичного исправления.
public function check($username, $password) {
global $db;
$sth = $db->prepare("SELECT user_id, password FROM users WHERE username = ?");
$sth->execute(array($username));
if($sth->rowCount() == 1) {
list($db_user_id, $db_password) = $sth->fetch(PDO::FETCH_NUM);
if(md5($db_password . $this->salt) == $password) {
$this->user_id = $db_user_id;
...
Еще раз, мы готовим запрос с заполнителями, затем выполняем с фактическими переменными. Опять же, мы хотим только один ряд, но на этот раз мы хотим, чтобы все подряд. Мы будем использовать PDO::FETCH_NUM
, чтобы сообщить fetch
, что нам нужен числовой индексированный массив, затем возьмем две результирующие записи в массиве и поместим их в $db_user_id
и $db_password
используя их там, где старый код называется mysql_result
. PDO не позволяет выбирать разные столбцы из одной строки, используя fetchColumn
.
Если вы хотите использовать вместо этого расширение mysqli
, вам нужно проделать еще немного работы. Я надеюсь, что убедил вас использовать PDO вместо этого!
Остальная часть класса, да, достаточно. Обязательно измените переменную класса $domain
в верхней части, чтобы она соответствовала вашему фактическому имени домена, она используется в файлах cookie.