как я могу фильтровать и дезинфицировать параметры URL в slim 3 [duplicate]

Код на основе Ответ Tolli .

#decorator, modyfies new_cls
def _singleton(new_cls):
    instance = new_cls()                                              #2
    def new(cls):
        if isinstance(instance, cls):                                 #4
            return instance
        else:
            raise TypeError("I can only return instance of {}, caller wanted {}".format(new_cls, cls))
    new_cls.__new__  = new                                            #3
    new_cls.__init__ = lambda self: None                              #5
    return new_cls


#decorator, creates new class
def singleton(cls):
    new_cls = type('singleton({})'.format(cls.__name__), (cls,), {} ) #1
    return _singleton(new_cls)


#metaclass
def meta_singleton(name, bases, attrs):
    new_cls = type(name, bases, attrs)                                #1
    return _singleton(new_cls)

Объяснение:

  1. Создайте новый класс, наследующий от данного cls (it не изменяет cls в случае, если кто-то хочет, например, singleton(list))
  2. Создать экземпляр. Перед переопределением __new__ это так просто.
  3. Теперь, когда у нас есть легко созданный экземпляр, переопределяет __new__ с использованием метода, определенного момента назад.
  4. Функция возвращает instance только в том случае, если это то, что ожидает абонент, в противном случае возникает TypeError. Условие не выполняется, если кто-то пытается наследовать от украшенного класса.
  5. Если __new__() возвращает экземпляр cls, то метод __init__() нового экземпляра будет вызван как __init__(self[, ...]), где self - это новый экземпляр, а остальные аргументы те же, что и в __new__(). instance уже инициализирован, поэтому функция заменяет __init__ функцией, ничего не выполняющей.

Посмотрите, как он работает в сети

995
задан davejal 7 January 2016 в 15:33
поделиться

18 ответов

Это распространенное заблуждение, что пользовательский ввод может быть отфильтрован. PHP даже имеет (теперь устаревшую) «функцию», называемую магическими кавычками, которая основывается на этой идее. Это вздор. Забудьте о фильтрации (или очистке или о том, что люди назовут ее).

Что вы должны делать, чтобы избежать проблем, достаточно просто: всякий раз, когда вы вставляете строку в внешний код, вы должны избегать ее, согласно правила этого языка. Например, если вы вставляете строку в какой-то SQL-таргетинг на MySql, для этой цели вы должны вывести строку с функцией MySql (mysqli_real_escape_string). (Или, в случае баз данных, использование подготовленных операторов - лучший подход, когда это возможно)

Другим примером является HTML: если вы вставляете строки в разметку HTML, вы должны избегать его с помощью htmlspecialchars . Это означает, что каждый оператор echo или print должен использовать htmlspecialchars.

Третий пример может быть командами оболочки: если вы собираетесь встраивать строки (такие как аргументы) в внешние команды, и назовите их с помощью exec , вы должны использовать escapeshellcmd и escapeshellarg .

И так и т. д. ...

Случай только , в котором вам необходимо активно фильтровать данные, - это если вы принимаете предварительно отформатированный ввод. Например. если вы позволите своим пользователям размещать HTML-разметку, которую вы планируете отображать на сайте. Однако вы должны быть разумны, чтобы избежать этого любой ценой, так как независимо от того, насколько хорошо вы его фильтруете, это всегда будет потенциальная дыра в безопасности.

1082
ответ дан BoffinbraiN 22 August 2018 в 19:20
поделиться
  • 1
    «Это означает, что каждое заявление эха или печати должно использовать htmlspecialchars & quot; - конечно, вы имеете в виду & quot; каждый ... оператор, выводящий пользовательский ввод & quot ;; htmlspecialchars () - ifying & quot; echo 'Hello, world!'; & quot; был бы сумасшедшим;) – Bobby Jack 20 October 2008 в 14:32
  • 2
    Отличный краткий ответ! Я съеживаюсь, когда слышу о дезинфекции материалов без учета контекста. – Cory House 23 May 2009 в 04:59
  • 3
    Есть один случай, когда я считаю, что фильтрация - правильное решение: UTF-8. Вы не хотите иметь недопустимые последовательности UTF-8 по всему вашему приложению (вы можете получить другое восстановление ошибок в зависимости от пути к коду), и UTF-8 можно легко фильтровать (или отклонять). – Kornel 9 September 2009 в 22:33
  • 4
    @porneL: Да, и также может быть полезно отфильтровать контрольные символы, отличные от новой строки, на этом этапе. Однако, учитывая, что большинство PHP-приложений даже не могут получить HTML-экранирование, я не собираюсь продвигать проблему с чередованием UTF-8 (они действительно являются проблемой в IE6 pre-Service-Pack-2 и старых опер). – bobince 27 November 2009 в 21:22
  • 5
    @jbyrd - нет, LIKE использует специализированный язык регулярных выражений. Вам придется избегать строки ввода дважды - один раз для регулярного выражения и один раз для кодировки строки mysql. Это код внутри кода внутри кода. – troelskn 29 October 2011 в 21:02

PHP 5.2 представил функцию filter_var.

Он поддерживает большое количество фильтров SANITIZE, VALIDATE.

http://php.net/manual/en/ function.filter-var.php

18
ответ дан dangel 22 August 2018 в 19:20
поделиться

Нет. Вы не можете полностью фильтровать данные без какого-либо контекста того, для чего это необходимо. Иногда вы хотите взять SQL-запрос в качестве входных данных, и иногда вы хотите взять HTML в качестве входных данных.

Вам нужно отфильтровать ввод в белом списке - убедитесь, что данные соответствуют некоторой спецификации того, что вы ожидаете. Затем вам нужно уйти от него, прежде чем использовать его, в зависимости от контекста, в котором вы его используете.

Процесс экранирования данных для SQL - для предотвращения внедрения SQL - сильно отличается от процесса экранирования данные для (X) HTML, чтобы предотвратить XSS.

72
ответ дан Daniel Papasian 22 August 2018 в 19:20
поделиться
  • 1
    +1 «Вы не можете в целом фильтровать данные без какого-либо контекста того, для чего это необходимо». Следует повторять чаще. – Ben 8 May 2012 в 07:07
function clean_input($data) {
  $data = trim($data);
  $data = stripslashes($data);
  $data = htmlspecialchars($data);
  return $data;
}
0
ответ дан Erik Thiart 22 August 2018 в 19:20
поделиться
  • 1
    Хотя этот код может ответить на вопрос, лучше объяснить, как решить проблему и предоставить код в качестве примера или ссылки. Кодовые ответы могут вводить в заблуждение и не иметь контекста. – Robert Columbia 21 August 2018 в 22:34
  • 2
    – Erik Thiart 15 October 2018 в 08:05

Один трюк, который может помочь в конкретном случае, когда у вас есть страница типа /mypage?id=53, и вы используете id в предложении WHERE, чтобы убедиться, что идентификатор определенно является целым числом, например:

if (isset($_GET['id'])) {
  $id = $_GET['id'];
  settype($id, 'integer');
  $result = mysql_query("SELECT * FROM mytable WHERE id = '$id'");
  # now use the result
}

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

15
ответ дан Hamish Downer 22 August 2018 в 19:20
поделиться
  • 1
    Вместо этого я использую $ id = intval ($ id) :) – Silentbang 22 July 2013 в 07:58
  • 2
    Кастинг целое является хорошим способом обеспечения ввода только числовых данных. – nn2 22 December 2014 в 04:03
  • 3
    $id = (int)$_GET['id'] и $que = sprintf('SELECT ... WHERE id="%d"', $id) тоже хороши – vladkras 21 November 2016 в 15:40

Чтобы устранить проблему XSS, посмотрите Очиститель HTML . Он достаточно настраиваемый и имеет достойную запись.

Что касается атак SQL-инъекций, убедитесь, что вы проверяете ввод пользователя, а затем запустите его, хотя mysql_real_escape_string (). Однако функция не будет побеждать во всех атаках на инъекции, поэтому важно проверить данные перед тем, как сбросить их в строку запроса.

Лучшим решением является использование подготовленных операторов. Это библиотека PDO и расширение mysqli поддерживают их.

20
ответ дан jasonbar 22 August 2018 в 19:20
поделиться

Самый простой способ избежать ошибок при дезинфекции входных данных и экранирующих данных - использовать фреймворк PHP, такой как Symfony , Nette и т. д. или часть этой структуры (механизм шаблонов, уровень базы данных, ORM).

Шаблонный движок, такой как Twig или Latte, имеет выход по умолчанию - вам не нужно решать вручную, если вы правильно экранировали свой вывод в зависимости от контекста (HTML или Javascript на веб-странице).

Framework автоматически дезинфицирует входные данные, и вы должны использовать переменные $ _POST, $ _GET или $ _SESSION напрямую, но через механизм, такой как маршрутизация, обработка сеансов и т. д.

И для уровня базы данных (модели) существуют рамки ORM, такие как Doctrine или обертки вокруг PDO, такие как Nette Database.

Здесь вы можете узнать больше об этом - Что такое программная среда?

3
ответ дан Jon Winstanley 22 August 2018 в 19:20
поделиться

Способы дезинфекции ввода пользователя с помощью PHP:

  • Использовать современные версии MySQL и PHP.

  • Установите кодировку явно:

    $mysqli->set_charset("utf8");
    manual
    $pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF8', $user, $password);
    manual
    $pdo->exec("set names utf8");
    manual
    $pdo = new PDO(
    "mysql:host=$host;dbname=$db", $user, $pass, 
    array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
    )
    );
    manual
    mysql_set_charset('utf8')
    [устарела в PHP 5.5.0, удалена в PHP 7.0.0].
  • Использовать безопасные кодировки:

    Выберите utf8, latin1, ascii .., не используйте уязвимые кодировки big5, cp932, gb2312, gbk, sjis.
  • Использовать пространственную функцию:

    Подготовленные команды MySQLi:
    $stmt = $mysqli->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); 
    $param = "' OR 1=1 /*";
    $stmt->bind_param('s', $param);
    $stmt->execute();
    PDO :: quote () - помещает кавычки вокруг (если требуется) и экранирует специальные символы во входной строке, используя стиль цитирования, соответствующий базовому драйверу:
    $pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF8', $user, $password);explicit set the character set
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);disable emulating prepared statements to prevent fallback to emulating statements that MySQL can't prepare natively (to prevent injection)
    $var = $pdo->quote("' OR 1=1 /*");not only escapes the literal, but also quotes it (in single-quote ' characters) $stmt = $pdo->query("SELECT * FROM test WHERE name = $var LIMIT 1");
    Подготовленные отчеты PDO : vs подготовленные операторы MySQLi поддерживают больше драйверов баз данных и именованных параметров :
    $pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF8', $user, $password);explicit set the character set
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);disable emulating prepared statements to prevent fallback to emulating statements that MySQL can't prepare natively (to prevent injection) $stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); $stmt->execute(["' OR 1=1 /*"]);
    mysql_real_escape_string [устарела в PHP 5.5.0, удалена в PHP 7.0.0]. mysqli_real_escape_string Вызывает специальные символы в строке для использования в инструкции SQL, принимая во внимание текущую кодировку соединения. Но рекомендуется использовать подготовленные заявления, потому что они не просто экранированные строки, а инструкция содержит полный план выполнения запроса, включая таблицы и индексы, которые он будет использовать, это оптимизированный способ. Используйте одиночные кавычки ('') вокруг ваших переменных внутри вашего запроса.
  • Проверить переменную содержит то, что вы ожидаете:

    Если вы ожидаете целое число, используйте:
    ctype_digit — Check for numeric character(s);
    $value = (int) $value;
    $value = intval($value);
    $var = filter_var('0755', FILTER_VALIDATE_INT, $options);
    Для использования строк:
    is_string() — Find whether the type of a variable is string
    Используйте Функция фильтра filter_var () - фильтрует переменную с указанным фильтром:
    $email = filter_var($email, FILTER_SANITIZE_EMAIL);
    $newstr = filter_var($str, FILTER_SANITIZE_STRING);
    более предопределенные фильтры filter_input () - получает определенную внешнюю переменную по имени и, возможно, ее фильтрует :
    $search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS);
    preg_match () - выполнить регулярное выражение; Напишите свою собственную функцию проверки.
4
ответ дан Mark Martin 22 August 2018 в 19:20
поделиться

Нет, это не так.

Прежде всего, SQL-инъекция - это проблема фильтрации входных данных, а XSS - выход с экранированием - поэтому вы даже не выполняли бы эти две операции одновременно в жизненном цикле кода.

Основные правила большого пальца

  • Для SQL-запроса, свяжите параметры (как с PDO) или используйте собственную функцию экранирования для переменных запроса (например, как mysql_real_escape_string())
  • Используйте strip_tags(), чтобы отфильтровать нежелательный HTML
  • . Выйдите из другого выхода с помощью htmlspecialchars() и обратите внимание на 2-й и 3-й параметры здесь.
39
ответ дан Peter Bailey 22 August 2018 в 19:20
поделиться
  • 1
    Таким образом, вы используете только strip_tags () или htmlspecialchars (), когда знаете, что на входе есть HTML-код, который вы хотите удалить или избежать соответственно - вы не используете его для какой-либо цели безопасности? Кроме того, когда вы выполняете привязку, что он делает для таких вещей, как Bobby Tables? & Quot; Роберт '); DROP TABLE Студенты; - & quot; Это просто избегает цитат? – Robert Mark Bram 29 October 2012 в 03:16
  • 2
    Если у вас есть пользовательские данные, которые будут поступать в базу данных, а затем будут отображаться на веб-страницах, обычно ли это не читается намного больше, чем написано? Для меня имеет смысл фильтровать его один раз (как вход) перед его сохранением, вместо того, чтобы фильтровать его каждый раз, когда вы его показываете. Я что-то пропустил или куча людей голосует за ненужные накладные расходы в этом и принятом ответе? – jbo5112 30 April 2014 в 15:07
  • 3
    Лучший ответ для меня. Это коротко и хорошо подходит к вопросу, если вы спросите меня. Можно ли как-то атаковать PHP через $ _POST или $ _GET с некоторой инъекцией или это невозможно? – Jo Smo 14 July 2014 в 13:26

Не пытайтесь предотвратить внедрение SQL путем дезинфекции входных данных.

Вместо этого не позволяйте использовать данные при создании кода SQL. Используйте подготовленные выражения (т. Е. Используя параметры в запросе шаблона), который использует связанные переменные. Это единственный способ гарантировать, что SQL-инъекция будет невозможна.

Подробнее о предотвращении SQL-инъекции см. На моем сайте http://bobby-tables.com/ .

185
ответ дан scorpiodawg 22 August 2018 в 19:20
поделиться
  • 1
    Или посетите официальную документацию и изучите PDO и подготовленные заявления. Крошечная кривая обучения, но если вы хорошо знаете SQL, вам не составит труда адаптироваться. – a coder 13 November 2014 в 03:49
  • 2
    Для конкретного случая SQL Injection, этот является правильным ответом! – Scott Arciszewski 30 May 2015 в 02:04
  • 3
    Обратите внимание, что подготовленные операторы не добавляют никакой безопасности, с параметризованными запросами. Их просто очень легко использовать вместе в PHP. – Basic 16 August 2015 в 03:01
  • 4
    Это не единственный гарантированный способ. Hex также предотвратит вход и unhex в запросе. Кроме того, шестнадцатеричные атаки невозможны, если вы используете hexing right. – Ramon Bakker 22 February 2016 в 16:50
  • 5
    Что делать, если вы вводите что-то специализированное, например, адреса электронной почты или имена пользователей? – Black_Stormy 9 January 2017 в 09:34

Если вы используете PostgreSQL, вход с PHP может быть экранирован с помощью pg_escape_string ()

 $username = pg_escape_string($_POST['username']);

Из документации ( http://php.net/manual/es/ function.pg-escape-string.php ):

pg_escape_string () выводит строку для запроса базы данных. Он возвращает escape-строку в формате PostgreSQL без кавычек.

4
ответ дан Shafiqul Islam 22 August 2018 в 19:20
поделиться

Вы никогда не санируете вход.

Вы всегда дезинфицируете вывод.

Преобразования, которые вы применяете к данным, чтобы сделать их безопасными для включения в оператор SQL, полностью отличаются от применяемых вами для включения в HTML полностью отличаются от тех, которые вы применяете для включения в Javascript, полностью отличаются от тех, которые вы применяете для включения в LDIF, полностью отличаются от тех, которые вы применяете для включения в CSS, полностью отличаются от тех, которые вы применяете для включения в электронную почту. ...

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

Давным-давно кто-то пытался изобрести одноразмерный механизм для экранирования данных, и мы закончили с помощью « magic_quotes », который не обеспечивал надлежащее удаление данных для всех целей вывода и приводил к другой установке, требующей работы другого кода.

1
ответ дан symcbean 22 August 2018 в 19:20
поделиться

Существует расширение фильтра ( howto-link , manual ), что очень хорошо работает со всеми переменными GPC. Это не волшебное дело, но вам все равно придется его использовать.

0
ответ дан Till 22 August 2018 в 19:20
поделиться

Что вы здесь описываете, это две отдельные проблемы:

  1. Санитация / фильтрация пользовательских входных данных.
  2. Выход экранирования.

1) Пользовательский вход всегда должен считаться плохим.

Использование подготовленных операторов или / и фильтрация с помощью mysql_real_escape_string, безусловно, необходимо. PHP также имеет встроенный filter_input, в котором есть хорошее место для запуска.

2) Это большая тема, и это зависит от контекста выводимых данных. Для HTML существуют такие решения, как htmlpurifier. как правило, всегда избегайте всего, что вы выводите.

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

Методы Выход PHP

Более безопасный выход PHP

10
ответ дан Tony Stark 22 August 2018 в 19:20
поделиться

Просто хотел добавить, что в вопросе выхода escaping, если вы используете PHP DOMDocument, чтобы сделать свой вывод html, он автоматически выйдет в правильном контексте. Атрибут (значение = "") и внутренний текст строки & lt; span & gt; не равны. Чтобы быть в безопасности от XSS, прочитайте следующее: Защитный чехол OWASP XSS

2
ответ дан user138720 22 August 2018 в 19:20
поделиться

Лучший метод BASIC для дезинфекции ввода пользователя с помощью PHP:


    function sanitizeString($var)
    {
        $var = stripslashes($var);
        $var = strip_tags($var);
        $var = htmlentities($var);
        return $var;
    }

    function sanitizeMySQL($connection, $var)
    {
        $var = $connection->real_escape_string($var);
        $var = sanitizeString($var);
        return $var;
    }
-4
ответ дан vuchkov 22 August 2018 в 19:20
поделиться
  • 1
    Таким образом, вы используете real_escape_string() для выхода из специальных символов SQL, а затем запустите sanitizeString(), который запускает stripslashes(), и удаляет любое экранирование, которое было выполнено. Поэтому в основном добавьте защиту SQL, а затем удалите ее на том же шаге. Почему вы даже используете stripslashes? Эти две функции являются ужасным способом дезинфекции даже для ОСНОВНОЙ санитарии. – cryptic ツ 5 August 2017 в 11:49

Нет функции catchall, потому что есть несколько проблем, которые необходимо решить.

  1. SQL Injection. Сегодня, как правило, каждый PHP-проект должен использовать готовые инструкции через PHP Data Objects ( PDO) в качестве наилучшей практики , предотвращающей ошибку от бродячей цитаты, а также полнофункциональное решение против инъекций . Это также самый гибкий & amp; безопасный способ доступа к вашей базе данных. Проверьте (Единственный правильный) учебник PDO для почти всего, что вам нужно знать о PDO. (Искренняя благодарность главному вкладчику SO, @YourCommonSense, за этот отличный ресурс по этому вопросу.)
  2. XSS - Sanitize data на пути в ... HTML очиститель был вокруг долгое время и по-прежнему активно обновляется. Вы можете использовать его для дезинфекции вредоносного ввода, в то же время предоставляя щедрые & amp; настраиваемый белый список тегов. Отлично работает со многими редакторами WYSIWYG, но для некоторых случаев использования может быть тяжело. В других случаях, когда мы вообще не хотим принимать HTML / Javascript, я нашел эту простую функцию полезной (и прошел несколько проверок против XSS): /* Prevent XSS input */ function sanitizeXSS () { $_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING); $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); $_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST; }
  3. XSS - Sanitize data на выходе ... если вы не гарантируете, что данные были надлежащим образом дезинфицированы до того, как вы добавите их в свою базу данных, вам нужно будет дезинфицировать его перед отображением его вашему пользователю, мы можем использовать эти полезные функции PHP: когда вы вызываете echo или print, чтобы отображать пользовательские значения, используйте htmlspecialchars , если данные не были надлежащим образом дезинфицированы и разрешено отображать HTML. json_encode является безопасным способом предоставления пользовательских значений от PHP до Javascript
  4. Вы вызываете внешние команды оболочки с помощью exec() или system() или к оператору backtick ? Если это так, в дополнение к SQL Injection & amp; XSS у вас может возникнуть дополнительная проблема для адресации пользователей, выполняющих вредоносные команды на вашем сервере . Вам нужно использовать escapeshellcmd , если вы хотите избежать всей команды OR escapeshellarg , чтобы избежать отдельных аргументов.
3
ответ дан webaholik 22 August 2018 в 19:20
поделиться

У PHP теперь есть новые хорошие функции filter_input, которые, например, освобождают вас от поиска «конечного регулярного выражения электронной почты» теперь, когда есть встроенный тип FILTER_VALIDATE_EMAIL

Мой собственный класс фильтра (использует javascript для выделения ошибочных полей) может быть инициирован либо ajax-запросом, либо обычной почтой. (см. пример ниже)
/**
 *  Pork.FormValidator
 *  Validates arrays or properties by setting up simple arrays. 
 *  Note that some of the regexes are for dutch input!
 *  Example:
 * 
 *  $validations = array('name' => 'anything','email' => 'email','alias' => 'anything','pwd'=>'anything','gsm' => 'phone','birthdate' => 'date');
 *  $required = array('name', 'email', 'alias', 'pwd');
 *  $sanatize = array('alias');
 *
 *  $validator = new FormValidator($validations, $required, $sanatize);
 *                  
 *  if($validator->validate($_POST))
 *  {
 *      $_POST = $validator->sanatize($_POST);
 *      // now do your saving, $_POST has been sanatized.
 *      die($validator->getScript()."<script type='text/javascript'>alert('saved changes');</script>");
 *  }
 *  else
 *  {
 *      die($validator->getScript());
 *  }   
 *  
 * To validate just one element:
 * $validated = new FormValidator()->validate('blah@bla.', 'email');
 * 
 * To sanatize just one element:
 * $sanatized = new FormValidator()->sanatize('<b>blah</b>', 'string');
 * 
 * @package pork
 * @author SchizoDuckie
 * @copyright SchizoDuckie 2008
 * @version 1.0
 * @access public
 */
class FormValidator
{
    public static $regexes = Array(
            'date' => "^[0-9]{1,2}[-/][0-9]{1,2}[-/][0-9]{4}\$",
            'amount' => "^[-]?[0-9]+\$",
            'number' => "^[-]?[0-9,]+\$",
            'alfanum' => "^[0-9a-zA-Z ,.-_\\s\?\!]+\$",
            'not_empty' => "[a-z0-9A-Z]+",
            'words' => "^[A-Za-z]+[A-Za-z \\s]*\$",
            'phone' => "^[0-9]{10,11}\$",
            'zipcode' => "^[1-9][0-9]{3}[a-zA-Z]{2}\$",
            'plate' => "^([0-9a-zA-Z]{2}[-]){2}[0-9a-zA-Z]{2}\$",
            'price' => "^[0-9.,]*(([.,][-])|([.,][0-9]{2}))?\$",
            '2digitopt' => "^\d+(\,\d{2})?\$",
            '2digitforce' => "^\d+\,\d\d\$",
            'anything' => "^[\d\D]{1,}\$"
    );
    private $validations, $sanatations, $mandatories, $errors, $corrects, $fields;


    public function __construct($validations=array(), $mandatories = array(), $sanatations = array())
    {
        $this->validations = $validations;
        $this->sanatations = $sanatations;
        $this->mandatories = $mandatories;
        $this->errors = array();
        $this->corrects = array();
    }

    /**
     * Validates an array of items (if needed) and returns true or false
     *
     */
    public function validate($items)
    {
        $this->fields = $items;
        $havefailures = false;
        foreach($items as $key=>$val)
        {
            if((strlen($val) == 0 || array_search($key, $this->validations) === false) && array_search($key, $this->mandatories) === false) 
            {
                $this->corrects[] = $key;
                continue;
            }
            $result = self::validateItem($val, $this->validations[$key]);
            if($result === false) {
                $havefailures = true;
                $this->addError($key, $this->validations[$key]);
            }
            else
            {
                $this->corrects[] = $key;
            }
        }

        return(!$havefailures);
    }

    /**
     *
     *  Adds unvalidated class to thos elements that are not validated. Removes them from classes that are.
     */
    public function getScript() {
        if(!empty($this->errors))
        {
            $errors = array();
            foreach($this->errors as $key=>$val) { $errors[] = "'INPUT[name={$key}]'"; }

            $output = '$$('.implode(',', $errors).').addClass("unvalidated");'; 
            $output .= "new FormValidator().showMessage();";
        }
        if(!empty($this->corrects))
        {
            $corrects = array();
            foreach($this->corrects as $key) { $corrects[] = "'INPUT[name={$key}]'"; }
            $output .= '$$('.implode(',', $corrects).').removeClass("unvalidated");';   
        }
        $output = "<script type='text/javascript'>{$output} </script>";
        return($output);
    }


    /**
     *
     * Sanatizes an array of items according to the $this->sanatations
     * sanatations will be standard of type string, but can also be specified.
     * For ease of use, this syntax is accepted:
     * $sanatations = array('fieldname', 'otherfieldname'=>'float');
     */
    public function sanatize($items)
    {
        foreach($items as $key=>$val)
        {
            if(array_search($key, $this->sanatations) === false && !array_key_exists($key, $this->sanatations)) continue;
            $items[$key] = self::sanatizeItem($val, $this->validations[$key]);
        }
        return($items);
    }


    /**
     *
     * Adds an error to the errors array.
     */ 
    private function addError($field, $type='string')
    {
        $this->errors[$field] = $type;
    }

    /**
     *
     * Sanatize a single var according to $type.
     * Allows for static calling to allow simple sanatization
     */
    public static function sanatizeItem($var, $type)
    {
        $flags = NULL;
        switch($type)
        {
            case 'url':
                $filter = FILTER_SANITIZE_URL;
            break;
            case 'int':
                $filter = FILTER_SANITIZE_NUMBER_INT;
            break;
            case 'float':
                $filter = FILTER_SANITIZE_NUMBER_FLOAT;
                $flags = FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND;
            break;
            case 'email':
                $var = substr($var, 0, 254);
                $filter = FILTER_SANITIZE_EMAIL;
            break;
            case 'string':
            default:
                $filter = FILTER_SANITIZE_STRING;
                $flags = FILTER_FLAG_NO_ENCODE_QUOTES;
            break;

        }
        $output = filter_var($var, $filter, $flags);        
        return($output);
    }

    /** 
     *
     * Validates a single var according to $type.
     * Allows for static calling to allow simple validation.
     *
     */
    public static function validateItem($var, $type)
    {
        if(array_key_exists($type, self::$regexes))
        {
            $returnval =  filter_var($var, FILTER_VALIDATE_REGEXP, array("options"=> array("regexp"=>'!'.self::$regexes[$type].'!i'))) !== false;
            return($returnval);
        }
        $filter = false;
        switch($type)
        {
            case 'email':
                $var = substr($var, 0, 254);
                $filter = FILTER_VALIDATE_EMAIL;    
            break;
            case 'int':
                $filter = FILTER_VALIDATE_INT;
            break;
            case 'boolean':
                $filter = FILTER_VALIDATE_BOOLEAN;
            break;
            case 'ip':
                $filter = FILTER_VALIDATE_IP;
            break;
            case 'url':
                $filter = FILTER_VALIDATE_URL;
            break;
        }
        return ($filter === false) ? false : filter_var($var, $filter) !== false ? true : false;
    }       



}

. Разумеется, имейте в виду, что вам нужно также выполнять экранирование sql-запроса в зависимости от того, какой тип db используется (mysql_real_escape_string () бесполезен для SQL-сервера, например) , Вероятно, вы захотите обработать это автоматически на соответствующем уровне приложения, таком как ORM. Кроме того, как упоминалось выше: для вывода в html используют другие специализированные функции php, такие как htmlspecialchars;)

. Действительно, для разрешения ввода HTML с такими же разделенными классами и / или тегами зависит один из выделенных пакетов проверки xss. НЕ ПИШИТЕ СВОИ СОБСТВЕННЫЕ РЕГЕФЫ В ПАРДЕ HTML!

44
ответ дан Wesley Murch 22 August 2018 в 19:20
поделиться
  • 1
    Похоже, что это может быть удобный скрипт для проверки входных данных, но он полностью не имеет отношения к вопросу. – rjmunro 1 August 2011 в 15:50
  • 2
    с / sanatize / Sanitize / г; – Brock Hensley 18 March 2013 в 15:24
  • 3
    с / Sanitize / Sanitize / г; – Christian 19 February 2014 в 03:53
  • 4
    чай и хрусты? санировать: санировать – ch1pn3ss 28 January 2015 в 20:46
Другие вопросы по тегам:

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