каков правильный путь PDO в php, чтобы сделать UPDATE [duplicate]

с этой идеей глобальных переменных, я сохранил экземпляр MainActivity в onCreate (); Глобальная переменная Android

public class ApplicationController extends Application {

    public static MainActivity this_MainActivity;
}

и открыть диалоговое окно, подобное этому. он работал.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Global Var
    globals = (ApplicationController) this.getApplication();
    globals.this_MainActivity = this;
}

и в потоке открываю диалоговое окно, подобное этому.

AlertDialog.Builder alert = new AlertDialog.Builder(globals.this_MainActivity);
  1. Открыть MainActivity
  2. Запустить поток.
  3. Открыть диалог из потока -> work.
  4. Нажмите кнопку «Назад» (onCreate будет вызываться и удалить первую MainActivity)
  5. Запустится новая MainActivity. (и сохраните его экземпляр для глобалов)
  6. Откройте диалог из первого потока -> он откроется и будет работать.

:)

203
задан Your Common Sense 18 September 2015 в 16:13
поделиться

6 ответов

Названия таблиц и столбцов не могут быть заменены параметрами в PDO.

В этом случае вы просто захотите фильтровать и дезинфицировать данные вручную. Один из способов сделать это - передать сокращенные параметры функции, которая будет выполнять запрос динамически, а затем использовать оператор switch() для создания белого списка допустимых значений, которые будут использоваться для имени таблицы или имени столбца. Таким образом, пользовательский ввод никогда не попадает непосредственно в запрос. Например:

function buildQuery( $get_var ) 
{
    switch($get_var)
    {
        case 1:
            $tbl = 'users';
            break;
    }

    $sql = "SELECT * FROM $tbl";
}

Не оставляя случая по умолчанию или используя случай по умолчанию, который возвращает сообщение об ошибке, вы убедитесь, что используются только значения, которые вы хотите использовать.

179
ответ дан Your Common Sense 24 August 2018 в 23:32
поделиться

Использование первого не является по своей сути более безопасным, чем последнее, вам необходимо дезинформировать ввод, является ли он частью массива параметров или простой переменной. Поэтому я не вижу ничего плохого в использовании последней формы с $table, если вы убедитесь, что содержание $table безопасно (alphanum plus underscores?) Перед его использованием.

4
ответ дан Adam Bellaire 24 August 2018 в 23:32
поделиться

Я вижу, что это старый пост, но я нашел его полезным и подумал, что поделился бы решением, аналогичным тому, что предложил @kzqai:

У меня есть функция, которая получает два параметра, такие как ...

function getTableInfo($inTableName, $inColumnName) {
    ....
}

Внутри я проверяю массивы, которые я установил, чтобы убедиться, что доступны только таблицы и столбцы с «блаженными» таблицами:

$allowed_tables_array = array('tblTheTable');
$allowed_columns_array['tblTheTable'] = array('the_col_to_check');

Затем проверка PHP перед работающий PDO выглядит как ...

if(in_array($inTableName, $allowed_tables_array) && in_array($inColumnName,$allowed_columns_array[$inTableName]))
{
    $sql = "SELECT $inColumnName AS columnInfo
            FROM $inTableName";
    $stmt = $pdo->prepare($sql); 
    $stmt->execute();
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
11
ответ дан Don 24 August 2018 в 23:32
поделиться

Чтобы понять , почему связывает имя таблицы (или столбца), не работает, вы должны понимать, как работают заполнители в подготовленных операциях: они не просто заменяются как строки (соответственно экранированные) , и результат SQL выполнен. Вместо этого СУБД, попросившая «подготовить» заявление, содержит полный план запросов о том, как он будет выполнять этот запрос, включая те таблицы и индексы, которые он будет использовать, которые будут одинаковыми независимо от того, как вы заполняете заполнители.

План для SELECT name FROM my_table WHERE id = :value будет таким же, как вы его замените :value, но похожее подобное SELECT name FROM :table WHERE id = :value невозможно спланировать, потому что СУБД не знает, какую таблицу вы собираетесь выбрать from.

Это не то, что библиотека абстракции, такая как PDO, может или должна работать, либо потому, что она победит две ключевые цели подготовленных операторов: 1) позволить базе данных заранее решить, как запрос будет запущен и будет использовать один и тот же план несколько раз; и 2) для предотвращения проблем безопасности путем отделения логики запроса от ввода переменной.

126
ответ дан IMSoP 24 August 2018 в 23:32
поделиться

Что касается основного вопроса в этом потоке, другие сообщения дали понять, почему мы не можем привязывать значения к именам столбцов при подготовке операторов, так что вот одно из решений:

class myPdo{
    private $user   = 'dbuser';
    private $pass   = 'dbpass';
    private $host   = 'dbhost';
    private $db = 'dbname';
    private $pdo;
    private $dbInfo;
    public function __construct($type){
        $this->pdo = new PDO('mysql:host='.$this->host.';dbname='.$this->db.';charset=utf8',$this->user,$this->pass);
        if(isset($type)){
            //when class is called upon, it stores column names and column types from the table of you choice in $this->dbInfo;
            $stmt = "select distinct column_name,column_type from information_schema.columns where table_name='sometable';";
            $stmt = $this->pdo->prepare($stmt);//not really necessary since this stmt doesn't contain any dynamic values;
            $stmt->execute();
            $this->dbInfo = $stmt->fetchAll(PDO::FETCH_ASSOC);
        }
    }
    public function pdo_param($col){
        $param_type = PDO::PARAM_STR;
        foreach($this->dbInfo as $k => $arr){
            if($arr['column_name'] == $col){
                if(strstr($arr['column_type'],'int')){
                    $param_type = PDO::PARAM_INT;
                    break;
                }
            }
        }//for testing purposes i only used INT and VARCHAR column types. Adjust to your needs...
        return $param_type;
    }
    public function columnIsAllowed($col){
        $colisAllowed = false;
        foreach($this->dbInfo as $k => $arr){
            if($arr['column_name'] === $col){
                $colisAllowed = true;
                break;
            }
        }
        return $colisAllowed;
    }
    public function q($data){
        //$data is received by post as a JSON object and looks like this
        //{"data":{"column_a":"value","column_b":"value","column_c":"value"},"get":"column_x"}
        $data = json_decode($data,TRUE);
        $continue = true;
        foreach($data['data'] as $column_name => $value){
            if(!$this->columnIsAllowed($column_name)){
                 $continue = false;
                 //means that someone possibly messed with the post and tried to get data from a column that does not exist in the current table, or the column name is a sql injection string and so on...
                 break;
             }
        }
        //since $data['get'] is also a column, check if its allowed as well
        if(isset($data['get']) && !$this->columnIsAllowed($data['get'])){
             $continue = false;
        }
        if(!$continue){
            exit('possible injection attempt');
        }
        //continue with the rest of the func, as you normally would
        $stmt = "SELECT DISTINCT ".$data['get']." from sometable WHERE ";
        foreach($data['data'] as $k => $v){
            $stmt .= $k.' LIKE :'.$k.'_val AND ';
        }
        $stmt = substr($stmt,0,-5)." order by ".$data['get'];
        //$stmt should look like this
        //SELECT DISTINCT column_x from sometable WHERE column_a LIKE :column_a_val AND column_b LIKE :column_b_val AND column_c LIKE :column_c_val order by column_x
        $stmt = $this->pdo->prepare($stmt);
        //obviously now i have to bindValue()
        foreach($data['data'] as $k => $v){
            $stmt->bindValue(':'.$k.'_val','%'.$v.'%',$this->pdo_param($k));
            //setting PDO::PARAM... type based on column_type from $this->dbInfo
        }
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);//or whatever
    }
}
$pdo = new myPdo('anything');//anything so that isset() evaluates to TRUE.
var_dump($pdo->q($some_json_object_as_described_above));

Вышеуказанное это просто пример, поэтому, разумеется, copy-> paste не будет работать. Отрегулируйте для ваших потребностей. Теперь это может не обеспечить 100% -ную защиту, но позволяет контролировать имена столбцов, когда они «входят» как динамические строки и могут быть изменены в конце пользователя. Кроме того, нет необходимости создавать какой-либо массив с именами и типами столбцов таблицы, поскольку они извлекаются из information_schema.

0
ответ дан man 24 August 2018 в 23:32
поделиться

Часть меня удивляется, если вы могли бы предоставить свою собственную функцию санитарии так же просто, как это:

$value = preg_replace('/[^a-zA-Z_]*/', '', $value);

Я действительно не продумал это, но кажется, что удаление чего-либо, кроме символов и подчеркиваний может работать.

0
ответ дан Phil LaNasa 24 August 2018 в 23:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: