Передача большого количества полей из Javascript в PHP

#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. Подсказка: используйте подготовленные инструкции!