Я хочу взять URL-адрес, который не содержит никаких апострофов, запятых или амперсандов и сопоставляет их с записью в базе данных, которая может иметь один из этих символов.
Например:
mywebsite.com/bobs-big-boy mywebsite.com/tom--jerry mywebsite.com/one-two-three
переписать
index.php?name=bobs-big-boy index.php?name=tom--jerry index.php?name=bobs-big-boy
Затем в php я хочу использовать $ _GET ['name'] для соответствия записям
bob's big boy tom & jerry one, two, three
Теперь мой запрос выглядит так:
"SELECT * from the_records WHERE name=$NAME";
Я не могу изменить записи, потому что они являются бизнес-именами. Есть ли способ написать запрос, чтобы игнорировать амперсанды, запятые и апострофы в db?
Да, вы можете, но я уверен, что он проигнорирует любые индексы, которые у вас есть в столбце. И это отвратительно.
Что-то вроде
SELECT * FROM the_records WHERE replace(replace(replace(name, '''', ''), ',', ''), '&', '') = $NAME
Кстати, взяв такую переменную get и введя ее в запрос mysql, можно созреть для SQL-инъекции, насколько я знаю.
pg, я знаю, вы сказали, что не можете изменять / обновлять содержимое в базе данных, которую вы выбираете, но не препятствует ли вам делать таблицу в другой базе данных, на которую у вас есть доступ на запись? Вы могли бы просто создать карту имен URL-адресов для бизнес-имен, и в первый раз, когда вы примете метод замещения, это будет медленным.
Приветствую,
Мне потребовалось несколько минут, чтобы разобраться! На самом деле у вас есть несколько недостатков, поэтому я попытался решить проблему с различными предположениями, как указано ниже.
Вот набор предполагаемых входных данных из URL-адреса, как вытащил из вашего примера, наряду с атакой инъекции MySQL (только для хихиканья) и вариациями для бизнес-имен. Ключи – это ожидаемые URL-адреса, и значения соответствуют значениям базы данных.
<?php $names = array( 'bobs-big-boy'=>"bob's big boy", 'tom--jerry'=>'tom & jerry', 'tomjerry'=>'tom&jerry', 'one-two-three'=>'one, two, three', 'onetwothree'=>'one,two,three', "anything' OR 'haxor'='haxor"=>'die-haxor-die', ); ?>
Один из разумных способов избежать нехватки регулярных выражений mySQL заключается в использовании SOUNDEX, и этот подход, по-видимому, в основном будет работать в этом случае в зависимости от требуемого уровня точности, плотности и сходства имен клиентов и т. Д. Например, это генерирует значения soundex для приведенных выше значений:
$soundex_test = $names; $select = 'SELECT '; foreach ($soundex_test as $name=>$dbname) { echo '<p>'.$name.': '.soundex($name).' :: '.$dbname.': '.soundex($dbname).'</p>'; $select .= sprintf("SOUNDEX('%s'),", $name); } echo '<pre>MySQL queries with attack -- '.print_r($select,1).'</pre>';
Поэтому, полагая, что клиенты не называются «один, два, три» и отдельный, называемый «onetwothree», этот подход должен работать хорошо.
Чтобы использовать этот метод, ваши запросы будут выглядеть примерно так:
$soundex_unclean = $names; foreach ($soundex_unclean as $name=>$dbname) { $soundex_unclean[$name] = sprintf("SELECT * from the_records WHERE name SOUNDS LIKE '%s';", $name).' /* matches name field = ['.$dbname.'] */'; } echo '<pre>MySQL queries with attack -- '.print_r(array_values($soundex_unclean),1).'</pre>';
Тем не менее, вот пробег, который имеет дело с инъекционной атакой (обратите внимание на новую строку). Я знаю, что это не в центре вопроса, но аджреал упомянул об этом, поэтому я подумал и об этом:
$soundex_clean = $names; foreach ($soundex_clean as $name=>$dbname) { // strip out everything but alpha-numerics and dashes $clean_name = preg_replace('/[^[:alnum:]-]/', '', $name); $soundex_unclean[$name] = sprintf("SELECT * from the_records WHERE name SOUNDS LIKE '%s';", $clean_name).' /* matches name field = ['.$dbname.'] */'; } echo '<pre>MySQL queries with attack cleaned -- '.print_r($soundex_unclean,1).'</pre>';
Если такой подход не устраивает, и вы решили, что подход для замены inline достаточен, не забудьте также добавить замену запятой на микс. В качестве примера такого подхода я предполагаю, что одиночная кавычка, двойная кавычка, амперсанд и запятая (т.е. «,», «и») являются единственными четырьмя специальными символами, которые включены в базу данных, но удалены из URL и что любой другой неадминистративный символ, включая пробелы, преобразуется в тире (т.е. -).
Во-первых, прогон, который не касается атаки на инъекции:
$unclean = $names; foreach ($unclean as $name=>$dbname) { $regex_name = preg_replace('/[-]+/', '[^[:alnum:]]+', $name); $unclean[$name] = sprintf("SELECT * from the_records WHERE REPLACE(REPLACE(REPLACE(REPLACE(name, ',', ''), '&', ''), '\"', ''), \"'\", '') REGEXP '%s'", $regex_name); } echo '<pre>MySQL queries with attack -- '.print_r($unclean,1).'</pre>';
Во-вторых, запуск, который имеет дело с атакой:
$clean = $names; foreach ($clean as $name=>$dbname) { $regex_name = preg_replace('/[^[:alnum:]-]/', '', $name); $regex_name = preg_replace('/[-]+/', '[^[:alnum:]]+', $regex_name); $clean[$name] = sprintf("SELECT * from the_records WHERE REPLACE(REPLACE(REPLACE(REPLACE(name, ',', ''), '&', ''), '\"', ''), \"'\", '') REGEXP '%s'", $regex_name); } echo '<pre>MySQL queries with attack cleaned -- '.print_r($clean,1).'</pre>';
Aaaand, это достаточно мозговой штурм для меня на одну ночь! = О)
Используя функцию str_replace, мы возьмем параметр $ name и заменим
ampersands (&) with "" spaces (" ") with "-" commas (",") with "" apostrophes("'") with ""
str_replace (смешанный поиск $, смешанный $ replace, смешанный $ subject [, int & $ count])
$ Search = {"&", "", ",", "'"}
$ Replace = {"", "-", "", ""}
$ComparableString = str_replace($Search, $Replace, $_GET['name'])
После этого мы можем выполнить запрос sql:
$name = mysql_real_escape_string($name, $db_resource); SELECT * from the_records WHERE name='$name'
Это немного janky, но вы можете взорвать GET и построить ГДЕ на нескольких условиях.
Что-то вроде (непроверено):
$name_array = explode("-", $_GET['name']); $sql_str = "SELECT * FROM the_records WHERE "; $first_time = true; foreach($name_array as $name){ if ($name != ""){ if ($first_time){ $sql_str .= "name LIKE \"%".$name."%\""; $first_time = false; } else { $sql_str .= " AND name LIKE \"%".$name."%\""; } } }