Автор работы: Пользователь скрыл имя, 29 Декабря 2012 в 21:00, курсовая работа
MySQL – это одна из самых популярных и самых распространенных СУБД (система управления базами данных) в интернете. Она не предназначена для работы с большими объемами информации, но ее применение идеально для интернет сайтов, как небольших, так и достаточно крупных.
MySQL отличается хорошей скоростью работы, надежностью, гибкостью. Работа с ней, как правило, не вызывает больших трудностей. Поддержка сервера MySQL автоматически включается в поставку PHP.
Введение………………………………………………………………...2
1. СОЕДИНЕНИЕ РНР-СЦЕНАРИЕВ с таблицами MySQL ……….4
1.1.Соединение с сервером. Функция mysql_connect ………...4
1.2. Разрыв соединения с сервером. Функция mysql_close …..5
1.3. Создание базы данных. Функция CREATE DATABASE ..5
1.4. Выбор базы данных. Функция mysql_select_db…………..7
1.5 Обработка ошибок…………………………………………..7
1.6 Автоматизация подключения к MySQL. Файл (config.php)8
2. ВЫПОЛНЕНИЕ ЗАПРОСОВ К БАЗЕ ДАННЫХ ………………...10
2.1 Создание таблицы. Функция CREATE TABLE:…………...10
2.2 Вставка записей в таблицу. Функция INSERT…………….12
2.3 Удаление записей. Функция DELETE……………………...13
2.4 Обновление записей. Функция UPDATE…………………..13
3. MySQL И ПРОБЛЕМЫ БЕЗОПАСНОСТИ ……………………….23
3.1. Экранирование спецсимволов ……………………………..23
3.2. Шаблоны запросов и placeholders …………………………24
3.3 Пример применения СУБД MySQL………………………..29
4. Назначение и условия применения проекта……………………..34
4.1. Представление скрипта ……………………………………34
4.2. Системные требования …………………………………….34
4.3. Характеристика скрипта …………………………………..34
Заключение……………………………………………………………..35
Список использованной литературы…………………………………36
Приложение А…………………………………………………………3
Этот запрос удалит все записи из таблицы table, потому что выражение SQL 1=1 всегда истинно.
Рассмотрим два способы защиты от подобных ошибок или действий злоумышленника:
● Экранирование спецсимволов.
● Шаблоны запросов и placeholders.
3.1 Экранирование спецсимволов
Прежде чем передавать значения переменных формы в SQL-запросы, необходимо специальным образом экранировать в них некоторые символы (в частности, апостроф), например, поставить перед ними обратный слэш. Для вставки предназначена функция:
mysql_escape_string()
string mysql_escape_string(string $str)
Функция похожа на другую функцию addslashes(), однако она добавляет слэши перед более полным набором специальных символов. Практика показывает, что для текстовых данных можно применять и функцию addslashes() вместо mysql_escape_string(). Во многих скриптах так и делается.
По стандарту MySQL экранированию подвергаются символы, которые в РНР записываются так: "\х00", "\n", "\г", "\\", ""', "" и "\х1А".
В это число входит
символ с нулевым ASCII-кодом, а поэтому mysql_escape_string(
Экранирование символов это лишь способ записи корректных SQL-выражений, не более того. С данными ничего не происходит, и они хранятся в базе без дополнительных слэшей — так, как выглядели изначально, еще до экранирования.
С использованием mysql_escape_string()код предыдущего запроса выглядит так:
mysql_query(
"DELETE FROM table WHERE name='".mysql_escape_string($
Это длинно, неуклюже и некрасиво.
3.2 Шаблоны запросов и placeholders
Рассмотрим другое решение.
Вместо явного экранирования и вставки переменных в запрос на их место помещают специальные маркеры (placeholders, "хранители места"), обычно выглядящие как ?.
Те же значения, которые будут подставлены вместо них, передаются отдельно, дополнительными параметрами.
С использованием гипотетической функции mysql_qwo, код которой будет представлен ниже, предыдущий запрос может быть переписан так:
mysql_qw ('DELETE FROM table WHERE name=?', $name);
Запрос стал короче и лучше защищен: теперь мы уже при написании кода не сможем случайно пропустить вызов функции mysql_escape_string() и, таким образом, попасться на уловку хакера. Все преобразования происходят автоматически, внутри функции.
В листинге lib_mysql_qw.php содержится простейшая реализация функции mysql_qw() (qw — от англ. query wrapper, "обертка для запроса").
Имеется также библиотека
lib/Placeholder.php, обеспечивающая значительно более мощную поддержку языка placeholders: http://dklab.ru/chicken/30.
В большинстве ситуаций возможностей, предоставляемых функцией mysql_qw (), оказывается достаточно.
Листинг lib_mysql_qw.php
<?php ## Простейшая функция для работы с placeholders.
// result-set, mysql_qw ($connection_id, $query, $argl, $arg2 ...).
// - или -
// result-set mysql_qw($query, $argl, $arg2, ...)
// Функция выполняет запрос к MySQL через соединение, заданное как
// $connection_id (если не указано, то через последнее открытое).
// Параметр $query может
содержать подстановочные
// вместо которых будут
// аргументов $arg1, $arg2 и т. д. (по порядку), экранированные и
// заключенные в апострофы.
function mysql_qw()
{
// Получаем все аргументы
$args = func_get_args();
// Если первый параметр имеет тип "ресурс", то это ID-соединения.
$соnn = null;
if (is_resource($args[0])) $conn = array_shift($args);
// Формируем запрос по шаблону.
$query = call_user_func_array("mysql_
// Вызываем SQL-функцию.
return $conn!==null ? mysql_query($query, $conn): mysql_query($query);
}
// string mysql_make_qw($query, $argl, $arg2,...)
// Данная функция формирует SQL-запрос по шаблону $query,
// содержащему placeholders.
function mysql_make_qw()
{
$args = func_get_args();
// Получаем в $tmp1 ССЫЛКУ на шаблон запроса.
$tmp1 =& $args[0];
$tmp1 - str_replace("%", "%%", $tmp1);
$tmp1 = str_replace("?", "%s", $tmp1);
// После этого $args[0] также окажется измененным.
// Теперь экранируем все аргументы, кроме первого.
foreach ($args as $i=>$v)
{
if (!$i) continue; // это шаблон
if (is_int($v)) continue; // целые числа не нужно экранировать
$args[$i] = "'".mysql_escape_string($v)."'
}
//На всякий случай заполняем 20 последних аргументов недопустимыми
// значениями, чтобы в случае, если число "?" превышает количество
// параметров, выдавалась ошибка SQL-запроса (поможет при отладке).
for ($i=$c=count($args)-1; $i<$c+20; $i++)
$args[$i+1] = "UNKNOWN_PLACEHOLDER_$i";
// Формируем SQL-запрос.
return call_user_func_array("sprintf"
}
?>
Если убрать поясняющие записи, то размер файла lib_mysql_qw.php уменьшится почти в три раза:
<?php ## Простейшая функция для работы с placeholders.
function mysql_qw()
{
$args = func_get_args();
$соnn = null;
if (is_resource($args[0])) $conn = array_shift($args);
$query = call_user_func_array("mysql_
return $conn!==null ? mysql_query($query, $conn): mysql_query($query);
}
function mysql_make_qw()
{
$args = func_get_args();
$tmp1 =& $args[0];
$tmp1 - str_replace("%", "%%", $tmp1);
$tmp1 = str_replace("?", "%s", $tmp1);
foreach ($args as $i=>$v)
{
if (!$i) continue;
if (is_int($v)) continue;
$args[$i] = "'".mysql_escape_string($v)."'
}
for ($i=$c=count($args)-1; $i<$c+20; $i++)
$args[$i+1] = "UNKNOWN_PLACEHOLDER_$i";
return call_user_func_array("sprintf"
}
?>
Функция sprintf() воспринимает символ % как управляющий. Чтобы отменить его специальное действие, необходимо его удвоить, что и делается в функции. Затем ? заменяется на %s, для sprintf() это означает "взять очередной строковый аргумент".
Для удобства тестирования этого кода главная функция разбита на две, выделен код замены подстановочных знаков в функцию mysql_make_qw().
В листинге test_qw.php приведен пример того, как будут выглядеть SQL-запросы после подстановки placeholders.
Листинг test_qw.php
<?php
require_once "lib_mysql_qw.php";
require_once "mysql_connect.php";
// Представим, что мы - хакеры...
$name = "' OR '1";
// Допустимый запрос.
echo mysql_make_qw('DELETE FROM people WHERE name=?', $name)."<br>";
// Недопустимый запрос.
echo mysql_make_qw('DELETE FROM people WHERE name=? OR ?', $name)."<br>";
// Вот как выглядит выполнение запроса.
mysql_qw('DELETE FROM people WHERE name=? OR ?', $name)
or die(mysql_error());
?>
В результате работы скрипта будет сгенерирована следующая страница:
DELETE FROM people WHERE name='\' OR \'1'
DELETE FROM people WHERE name=' \ ' OR \ ' 1' OR id=UNKNOWN_PLACEHOLDER_l
Unknown column 'UNKNOWN_PLACEHOLDER_1' in 'where clause1
Перед апострофами в данных появились слэши, a placeholder, которому "не хватило" аргументов функции, оказался замененным на строчку UNKNOWN_PLACEHOLDER_l.
Теперь любая попытка выполнения такого запроса заранее обречена на неудачу (о чем говорит последнее диагностическое сообщение, сгенерированное вызовом die()), что является важным подспорьем при отладке сценариев.
3.3 Пример применения СУБД MySQL
Рассмотрим некоторые приемы, которые удобно применять в сценариях, требующих обращений к базе данных на примере гостевой книги. С книгой можно проделывать следующие два действия:
● добавлять новую запись; при этом она помечается текущей датой и помещается в таблицу базы данных;
● удалять некоторую запись по ее идентификатору.
Скрипт упрощен: удалять записи позволяется любому пользователю, а не только администратору сайта. При необходимости ограничить права легко: достаточно вставить в скрипт соответствующие проверки.
Листинг guestbook.php
<? php ## Простейшая гостевая книга.
require_once "mysql_connect.php";
require_once "lib_mysql_qw.php";
// Имя таблицы.
define("TBLNAME", "guestbook");
// Создаем таблицу, если она еще не существует.
mysql_qw ('CREATE TABLE IF NOT EXISTS '.TBLNAME.' (
id INT AUTO_INCREMENT PRIMARY KEY,
stamp TIMESTAMP,
name VARCHAR(60),
text TEXT
)
')
or die(mysql_error()) ;
// Обрабатываем кнопки и действия.
if (@$_REQUEST['doAdd'])
{
// Получаем данные из формы.
$element = $_REQUEST['element'];
// Удаляем слэши в данных, которые РНР вставил в режиме
// magic_quotes_gpc (если он включен).
if (ini_get("magic_quotes_gpc"))
$element = array_map('stripslashes', $element);
// Вставляем запись.
mysql_qw(
'INSERT INTO '.TBLNAME. 'SET name=?, text"?',
$element['name'], $element['text']
)
or die(mysql_error());
// Выполняем "самопереадресацию", чтобы при нажатии кнопки
// "Обновить" в браузере
сообщение не добавлялось
Header ("Location: {$_SERVER['SCRIPT_NAME']}?".
exit ();
}
// Удаление сообщения с указанным ID.
if ($delid = @$_REQUEST['delete'])
{
mysql_qw ('DELETE FROM '.TBLNAME.' WHERE id=?', $delid)
or die(mysql_error());
}
// Выбираем все записи из таблицы, начиная с самой новой.
$result = mysql_qw('
-- Функция MySQL UNIX_TIMESTAMP() конвертирует, timestamp
-- из формата MySQL в число секунд с начала эпохи Unix.
SELECT *, UNIX_TIMESTAMP(stamp) AS stamp
FROM ' . TBLNAME. '
ORDER BY stamp DESC
')
or die(mysql_error());
for ($book=array();
$row=mysql_fetch_array($
$book[]=$row);
?>
<! -- Далее идет шаблон книги. -->
<form action="" method="post">
<table>
<tr valign="top">
<td>Baшe имя:</td>
<td><input type ="text" name="element [name] "></td>
</tr>
<tr valign="top">
<td>Teкст сообщения:</td>
<td><textarea name="element[text]" cols="60" rows="5"></textarea></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" name="doAdd" value="Добавить"</td>
</table>
</form>
<hr>
<?
foreach($book as $element)
{
?>
<b>
<? =date ("d.m.Y", $element ['stamp'])?>
<? =htmlspecialchars ($element ['name'])?>
</b>
написал:
<a href="<?=$_SERVER['SCRIPT_
?>
">
[удалить]</a>
<br>
<blockquote>
<?=n12br(htmlspecialchars($
?>
</blockquote>
<hr>
<?
}
?>
Этот скрипт использует удобные на практике приемы.
● Вначале включают код mysql_connect.php для подключения к базе данных, а также библиотеку lib_mysql_qw.php для выполнения "защищенных" запросов.
Дальше ИСПОЛЬЗУЕТСЯ ТОЛЬКО ФУНКЦИЯ mysql_qw(), и не применяется вызов функции mysql_query() напрямую.
● Создается константа, хранящая имя таблицы гостевой книги в базе данных. Использование константы вместо явного указания имени позволяет в дальнейшем легко сменить имя таблицы (если это понадобится).
● Создается таблица guestbook, имеющая 4 поля (столбца):
○ Автоинкрементное поле id, как обычно, служит для идентификации записей.