Я бы всегда использовал «POST» для пользовательских данных сам, а не «GET», и следующее обсуждение отражает это, но вы все равно сможете использовать около 90% того, что я скажу ниже в любом случае.Итак, вот так ...
Общее правило: не думайте заранее, избегая данных.Только сделайте немедленно необходимые преобразования.Канонический пример: не переходите на HTML при вставке базы данных, так как в итоге вы получите, например, '&', превратившись в '& amp;'после пары туров.
Общее правило: Используйте UTF-8 повсюду.Вы будете благодарны за это в первый раз, когда кто-то сделает копию вставки из электронного письма с многоточием Юникода.(Вы будете удивлены, как часто это происходит.) Необходимы типичные настройки;это может варьироваться в зависимости от версии PHP / MySQL / HTML:
- PHP: php_value default_charset "UTF-8"
- MySQL: при создании базы данных выберите utf8.
- HTML:
Общее правило: только пять мест, куда могут перемещаться неанизированные (хотя и должным образом экранированные) пользовательские данные:
- Значение (правильно типизированного) поля базы данных (т. е. текстовое поле UTF-8 или поле большого двоичного объекта.)
- Значение переменной PHP.
- Значение переменной Javascript.
- Значение формы HTMLАтрибут 'value' элемента.
- Содержимое дочернего элемента textNode элемента HTML.
Если вы хотите поместить пользовательские данные в любое другое место, оно должнобыть продезинфицированным.Это выходит за рамки вопроса, но в типичном случае вы можете использовать регулярное выражение для замены всего, что не является буквой или цифрой ASCII, подчеркиванием.В тех случаях, когда уникальность имеет значение, например, имя файла или атрибут «id» в HTML, необходимо выполнить дополнительную работу, чтобы убедиться, что очищенные имена являются уникальными (например, убедитесь, что столкновение происходит, когда 'a ^ b' и 'a & b'оба очищаются до' a_b ').Типичное решение выглядит примерно так:
filename = original_filename;
while(already_exists(filename)) {count++; filename = original_filename + count;}
И, наконец, смысл моего ответа: специальные функции escape, используемые для перемещения данных в те пять специальных мест, куда могут попадать неизмененные пользовательские данные:1034 *
- Атрибут значения HTML-формы -> переменная PHP $ _POST: экранирование не требуется.
Переменная PHP -> поле базы данных: подготовленный оператор PDO:
$stmt = $db->prepare('insert into roundtrip (id, name) values (NULL, :data)');
$stmt->execute(array('data' => $_POST['name']));
Поле базы данных -> PHP-переменная: экранирование не требуется, но используйте подготовленный оператор PDO для экранирования значений запроса:
$stmt = $db->prepare('select id, name from roundtrip where name = :data');
$stmt->execute(array('data' => $_POST['name'])); // User data needs escaping.
while ($result = $stmt->fetch()) {
echo $result['name']; // DB result doesn't.
}
PHP-переменная -> переменная Javascript: json_encode:
var data = <?php echo json_encode(data); ?>;
PHP-переменная -> HTML textNode или значение формы: htmlspecialchars:
<div><?php echo htmlspecialchars(data); ?></div>
<input type="text" name="name" value="<?php echo htmlspecialchars(data); ?>"/>
Javascript <-> HTMLtextNode или значение формы: встроенные в браузер атрибуты / функции textNode и .value:
data = source_div.textContent; // Firefox
data = source_div.innerText; // Other browsers
target_div.textContent = data; // Firefox
target_div.innerText = data; // Other browsers
// To/from form element.
data = source_form.value;
target_form.value = data;
// Append to element.
target_div.appendChild(document.createTextNode(data)); // All browsers
// jQuery textNode
data = $('#source_div_id').text();
$('#target_div_id').text(data);
// jQuery form value
data = $('#source_form_id').val();
$('#target_form_id').val(data);
Выполните повторный тест в обе стороны с такой строкой, чтобы убедиться, что она всегда выполняетсячерез весь HTML-> PHP-> DB-> PHP-> [Javascript ->] HTML-цикл каждый раз точно такой же:
&ДЖäüöéè<script>…</script>™<i>bold</i>
Вот мой скрипт, который тестирует экранирование в разные стороны;ему, очевидно, нужна база данных, таблица с именем 'roundtrip' и столбцами 'id' и 'name', а также одна строка с id = 1, которую необходимо создать перед ее запуском:
<?php
$db = new PDO("mysql:host=$host;dbname=$dbname", $db_user, $db_password);
$stmt_insert = $db->prepare('
update
roundtrip
set
name = :name
where
id = 1
');
$stmt_select = $db->prepare('
select
name
from
roundtrip
where
id = 1
');
if ($_POST['do'] == 'edit') {
$stmt_insert->execute(array('name' => $_POST['name']));
}
$stmt_select->execute();
while ($result = $stmt_select->fetch()) {
$data = $result['name'];
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Roundtrip test</title>
<script type="text/javascript" src="/js/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
function copydiv() {
// Non-jquery:
//var source = document.getElementById('divdata');
//var target = document.getElementById('copydiv');
//if (typeof(source.textContent) != "undefined") {
// target.textContent = source.textContent;
//} else {
// target.innerText = source.innerText;
//}
// jquery:
$('#copydiv').text($('#divdata').text());
}
function copyform() {
// Non-jquery:
//var source = document.getElementById('formdata');
//var target1 = document.getElementById('copyform1');
//var target2 = document.getElementById('copyform2');
//if (typeof(source.textContent) != "undefined") {
// target1.textContent = source.value;
//} else {
// target1.innerText = source.value;
//}
//target2.value = source.value;
// jquery:
$('#copyform1').text($('#formdata').val());
$('#copyform2').val($('#formdata').val());
}
function copyjson() {
var data = <?php echo json_encode($data); ?>;
// Non-jquery:
//var target = document.getElementById('copyjson');
//if (typeof(target.textContent) != "undefined") {
// target.textContent = data;
//} else {
// target.innerText = data;
//}
// jquery:
$('#copyjson').text(data);
}
</script>
</head>
<body>
<div>Data: <span id="divdata"><?php echo htmlspecialchars($data); ?></span></div>
<div>JS div copy: <span id="copydiv"/></div>
<div>JS form copy: <span id="copyform1"/></div>
<div>JSON copy: <span id="copyjson"/></div>
<form method="POST">
<input type="hidden" name="do" value="edit"/>
<input type="text" name="name" id="formdata" value="<?php echo htmlspecialchars($data); ?>"/>
<input type="text" id="copyform2"/>
<input type="button" value="Copy div" onclick="copydiv();"/>
<input type="button" value="Copy form" onclick="copyform();"/>
<input type="button" value="Copy json" onclick="copyjson();"/>
<input type="submit"/>
</form>
</body>
</html>