#javascript #php #mysql
#javascript #php #mysql
Вопрос:
Я создаю страницу ввода данных с использованием JS, jQuery и PHP для базы данных MySQL с примерно 250 полями в клиентской таблице. Я не хотел иметь дело с передачей такого количества полей по отдельности между JS и PHP, поэтому я написал функцию для перебора всех элементов ввода данных и построения всего оператора SQL insert для передачи в PHP. Для каждого элемента ввода данных я создал пользовательский атрибут «fieldname», содержащий имя соответствующего поля базы данных, как в этом примере.
<input type='text' fieldname='first_name' ID='txtFirstName' maxlength=25>
Ниже приведена функция JS и PHP-код. Я протестировал это, и это работает, но идея передачи целого огромного оператора SQL, подобного этому, кажется странной.
Если у кого-либо было аналогичное требование для передачи большого количества полей, я хотел бы узнать об альтернативных решениях.
function InsertRecord() {
// Iterate through every data entry element with the "fieldname" attribute to create the field list for the SQL statement
sql_cmd='insert into clients('
$('[fieldname]').each( function() {
sql_cmd=sql_cmd $(this).attr('fieldname') ',';
});
sql_cmd=sql_cmd.slice(0, -1) ') values('; // slice gets rid of the last character (trailing comma)
// Iterate again to get the values
$('[fieldname]').each( function() {
sql_cmd=sql_cmd "'" $(this).val().replace(/'/g, "''") "',"; // replace single quotes in values with 2 single quotes
});
sql_cmd=sql_cmd.slice(0, -1) ')';
$.ajax({
type: 'POST',
url: 'nwcs.php',
data: { sql: sql_cmd },
dataType: 'text',
success: function(data) { alert(data) },
error: function(jqXHR, textStatus, errorThrown) { alert('Error', '<B>' errorThrown '</B>'); } });
}
PHP-код:
if (mysqli_query($conn, $sql)) {
echo 'Record added';
}
else {
header('HTTP/1.0 500');
die('Unable to insert record due to database error: ' . mysqli_error($conn));
}
Комментарии:
1. Я бы очень настоятельно рекомендовал вам отказаться от этого плана. Вы открываете свою базу данных для произвольных запросов из internet API.
2. Возможно, если вы опубликуете структуру полей в формате JSON, это было бы намного лучше.
3. Передача большого объема данных не является чем-то особенным и действительно необходима, если вы хотите … передать большой объем данных. Что является странным, так это то, что пользователь может определить фактический код SQL, который вы собираетесь выполнить. Это очень высокий уровень доверия, который вы испытываете к своим пользователям, предоставляя им прямой доступ к базе данных подобным образом.
4. Передавайте значения как обычные параметры; в конечном итоге это примерно тот же объем содержимого, и с обычными значениями вы можете использовать подготовленную инструкцию на сервере и защитить свою базу данных от грубых злоупотреблений.
5.
POST /nwcs.php
с теломDROP TABLE clients
.
Ответ №1:
Никогда не создавайте свой SQL-запрос на стороне клиента вашего приложения. Это огромная проблема безопасности. Любой может запустить любой произвольный запрос непосредственно к вашей базе данных таким образом, оставляя бреши кому-то, кто запускает что-то вроде упомянутого в комментарии @VLAZ.
Самый простой способ, который я могу придумать, — это присвоить вашим полям префикс типа table_1
, table_2
… Таким образом, вы можете перебирать свой массив $POST в поисках вашего table_
префикса.
foreach($_POST as $key => $value){
if (startsWith($key,"table_"))
{
// Append to your query string or something
}
}
Кроме того, имейте в виду атаки с использованием SQL-инъекций, которые были бы возможны без фильтрации пользовательского ввода. Вы можете начать изучать это на веб-сайте OWASP(https://owasp.org/www-community/attacks/SQL_Injection)
Комментарии:
1. Чтобы повторить вопрос в моем последнем комментарии, было бы лучше, если бы вместо создания всего оператора SQL на интерфейсе я передал имена полей и значения отдельно в PHP, а затем добавил «вставить в клиенты» на серверной части?
2. ДА. Таким образом, вы можете предотвратить запуск кем-либо произвольного SQL в вашей базе данных.
Ответ №2:
Вы могли бы сделать что-то вроде приведенных ниже строк:
// simplified Vanilla JavaScript version of jQuery.post:
function post(url,data,cbf){ // cbf: callback function
var xhr = new XMLHttpRequest();
xhr.open('POST',url);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {if (xhr.status === 200) {cbfamp;amp;cbf(JSON.parse(xhr.responseText));}};
xhr.send(Object.keys(data).map((k) => encodeURIComponent(k) '=' encodeURIComponent(data[k])).join('amp;'))
}
// scan all input fields:
document.querySelector('.go').onclick=ev=>{
ev.preventDefault();
let dat=[...ev.target.closest('form').children].reduce((a,c)=>{
if (c.tagName=='INPUT' amp;amp; c.value>'') a[c.name]=c.value;
return a;
}, {});
console.log(dat); // show data for upload in console
// -- uncomment the next line to activate the posting of data:
// post('nwcs.php',dat,response=>console.log(response))
// -- (the above will not work from stackoverflow.com)
}
<form name="frm">
<input type='text' name='first_name' ID='txtFirstName' maxlength=25 placeholder='first name'><br>
<input type='text' name='last_name' ID='txtLastName' maxlength=25 placeholder='last name'><br>
<input type='text' name='email' ID='txtEmail' maxlength=25 placeholder='Email'><br>
<input type='text' name='phone' ID='txtPhone' maxlength=25 placeholder='Phone'><br>
<button class="go">save</button>
</form>
Фактическое post()
не может произойти в этом фрагменте, но функция ванильного JavaScript post()
должна выполнить эту работу за вас в вашей «реальной» среде.
Затем вашему серверному скрипту nwcs.php
необходимо получить строку JSON и создать из нее несколько безопасных инструкций insert. Подсказка: используйте подготовленные инструкции!