如何循环$ _POST数组,其中$ _POST表单名称等于数据库列名称,并从MySQL注入中安全地执行?
我将拥有大约40个输入的表单。
例如,我有html表单( index.php ):
<form action="form.php" id="myForm" method="POST" enctype="multipart/form-data">
User: <input type="text" name="owner_name"><br>
User-email: <input type="text" name="owner_email"><br>
User-id: <input type="text" name="owner_id"><br>
Pictures: <br><input name="pictures[]" type="file" size="50" maxlength="100000" multiple><br>
<input type="submit" value="Send" />
</form>
我有 form.php 文件:
$pdo = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// Check connection
if ($pdo->connect_error) {
die("Connection failed: " . $pdo->connect_error);
}
$statement = $pdo->prepare("INSERT INTO claims_motor(owner_email, owner_name, owner_id)
VALUES(:owner_email, :owner_name, :owner_id)");
$statement->execute(array(
"owner_email" => $_POST['owner_email'],
"owner_name" => $_POST['owner_name'],
"owner_id" => $_POST['owner_id']
));
如何为$ _POST构建一个foreach循环,所以我不需要为40 $ _POST变量编写这段代码?
答案 0 :(得分:1)
正如其他人所说的那样,恶意用户可能会编辑DOM中字段的名称,但表示可能会对以下内容感兴趣。
$sql='insert into `claims_motor` (`'.implode( '`,`', array_keys( $_POST ) ) .'`) values (:'.implode(',:',array_keys( $_POST ) ).');';
foreach( $_POST as $field => $value ) $params[":{$field}"]=$value;
$statement = $pdo->prepare( $sql );
$statement->execute( $params );
在回答有关从输入数据中删除虚假html的问题时,您可以尝试以下方面的内容:
$options=array( 'flags'=>FILTER_FLAG_NO_ENCODE_QUOTES | FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_ENCODE_LOW | FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_AMP );
function filterfield( $field ){
global $options;
return ":".strip_tags( filter_var( $field, FILTER_SANITIZE_STRING, $options ) );
}
function filtervalue( $field ){
global $options;
return strip_tags( filter_input( INPUT_POST, $field, FILTER_SANITIZE_STRING, $options ) );
}
function isfield( &$field, $key, $fields ){
$field=in_array( $field, $fields ) ? $field : false;
}
$sql='insert into `claims_motor` (`'.implode( '`,`', array_keys( $_POST ) ) .'`) values (:'.implode(',:',array_keys( $_POST ) ).');';
foreach( $_POST as $field => $value ) $params[ filterfield( $field ) ]=filtervalue( $field );
我并不是说这是一个完美的解决方案,但它或多或少地回答了你原来的问题。 You can find out more about filters here
我尝试使用PDO并在值中包含DROP
语句,这是正常的 - 作为字符串数据插入。当我尝试修改字段名称时,它会导致PDOException
并且没有做任何其他事情....
要按照建议获取列名,可以尝试: -
$sql="select group_concat(`column_name`) as 'cols'
from `information_schema`.`columns`
where `table_schema`=database() and `table_name`=:table;";
$params=array(':table' => 'claims_motor');
$statement = $pdo->prepare( $sql );
$statement->execute( $params );
/* Process the recordset */
$cols=$rs->cols; /* or whatever method to access the record */
/* Filter fields that were not in form - if any */
$cols=explode( ',', $cols );
array_walk( $cols, 'isfield', array_keys( $_POST ) );
$fields = array_filter( $cols );
/* Prepare sql for the insert statment */
$sql_insert='insert into `claims_motor` (`'.implode( '`,`', $fields ) .'`) values (:'.implode( ',:', $fields ).');';
/* reset params array */
$params=array();
/* Construct new array of bound variables / params */
foreach( $_POST as $field => $value ) $params[ filterfield( $field ) ]=filtervalue( $field );
/* add the data to db */
$statement = $pdo->prepare( $sql );
$statement->execute( $params );