как передать $ order var в pdo в безопасном режиме [дубликат]

Расширение .jsf - это место, где FacesServlet находится во время периода JSF 1.2, часто отображаемого в web.xml.

<servlet-mapping> <servlet-name>facesServlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping>

Расширение .xhtml является фактическим файлом Facelets, так как вы физически помещены в webcontent вашего webapp, например. [F8].

Если вы вызываете эту страницу с расширением .jsf, например. http://localhost:8080/webapp/page.jsf, тогда будет вызываться FacesServlet, найти файл page.xhtml и проанализировать / отобразить его компоненты JSF. Если FacesServlet не вызывается, то конечный пользователь получит исходный код исходного кода XHTML (который можно увидеть правой кнопкой мыши, View Source).

Иногда расширение *.faces или /faces/* используется папка. Но это происходило со времен JSF 1.0 / 1.1. Вы можете выбирать и использовать любое сопоставление, которое вы хотели бы позволить прослушивать FacesServlet, даже если это ничего не говорит *.xyz. Сама фактическая страница всегда должна иметь расширение .xhtml, но это настраивается следующим <context-param> в web.xml:

<context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xml</param-value> </context-param>

Это изменит FacesServlet, чтобы найти page.xml instad of (default) page.xhtml.

Совсем недавно с JSF / Facelets 2.0 было использовано сопоставление *.xhtml. В JSF / Facelets 1.x нельзя было использовать то же расширение отображения, что и физический файл. Это приведет к бесконечному циклу. Но с JSF / Facelets 2.0 это возможно, и это позволяет вам вызвать страницу на http://localhost:8080/webapp/page.xhtml.

<servlet-mapping> <servlet-name>facesServlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping>

Таким образом, вам не нужно настраивать некоторые ограничения безопасности, чтобы скрыть исходные исходные файлы для случаев, когда конечный пользователь меняет, например, .jsf в URL-адресе .xhtml в адресной строке браузера , Только инструментальные средства (IDE и плагины) и учебные ресурсы по-прежнему нуждаются в том, чтобы догнать защищенный переход от *.jsf до *.xhtml. Согласно JSF 2.3, FacesServlet по умолчанию будет авторегистрацией на *.xhtml тоже (рядом с /faces/*, *.faces и *.jsf). Это обращено к Mojarra 2.2.11.

См. Также:

Можем ли мы использовать регулярные выражения в шаблонах URL web.xml? Установите домашнюю страницу по умолчанию через & lt; приветственный файл & gt; в проекте JSF JSF возвращает пустую / непроверенную страницу с открытым / исходным источником XHTML / XML / EL вместо визуализированного вывода HTML. В чем разница между созданием JSF-страниц с расширением .jsp или .xhtml или .jsf. Какие файлы XHTML мне нужно поставить in / WEB-INF, а какие нет? Настроить FacesServlet & lt; url-pattern & gt; чтобы избавиться от расширения .xhtml
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 в 16:46
поделиться

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

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

Я вижу, что это старый пост, но я нашел его полезным и подумал, что поделился бы решением, аналогичным тому, что предложил @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 в 16:46
поделиться

Чтобы понять , почему связывает имя таблицы (или столбца), не работает, вы должны понимать, как работают заполнители в подготовленных операциях: они не просто заменяются как строки (соответственно экранированные) , и результат 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 в 16:46
поделиться

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

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 в 16:46
поделиться

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

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

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

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

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