PHP екранувати символи. Екранування спецсимволів у регулярних виразах

У довіднику з регулярних висловів, є такий розділ, який називається "Мета-символи (екрануються)". Ось саме про ці мета символи (їх ще називають і спеціальні символи) і говоритимемо у цій статті.

Спеціальні символи - це символи, які є буквами чи цифрами. Тобто це все символи, окрім букв та цифр.

Спеціальними символами вважаються такі символи як точка, зірочка, плюс, питання, грати та інші.

Як ми знаємо з попередніх статей, деякі спеціальні символи мають особливу роль у регулярних виразах. Тобто кожен спеціальний символ має якесь уявлення.

Наприклад, точка означає абсолютно будь-який символ. Зірочка є квантором повторень від нуля до нескінченності. Плюс також є квантором повторень від одного до нескінченності. Уявний символ ^ означає початок рядка, а знак долара ($) кінець рядка. До речі, символ долара теж є уявним символом. Ще ми знаємо, що символ має і іншу роль, якщо ми поставимо його всередині квадратних дужок. Про всі ці значення ми поговорили в попередніх статтях.

У цій статті я відповім на питання "Як використовувати спеціальні символи в регулярному виразі".

Щоб скасувати цю особливу роль, у спеціального символу в регулярному вираженні, необхідно його екранувати . Таким чином, цей спеціальний символ представлятиме саме того символу, який є. Тобто екранована точка означає саме точка, а чи не будь-який символ. Екранована зірочка означає саме зірочка, а не квантифікатор повторень.

Екранування робиться за допомогою зворотного слішу. Тобто для того, щоб екранувати якийсь спеціальний символ, необхідно поставити перед ним зворотний сліш.

Припустимо, у нас є таке завдання "Перевірити, чи поставлено крапку в кінець рядка". Так ось для того, щоб ця точка в регулярному вираженні, була саме точкою, а не будь-яким іншим символом, необхідно її екранувати.

Var str = "Він є героєм."; var reg = /.*\.$/; alert(reg.test(str)); // true

Як бачимо, результатом перевірки рядки на відповідність регулярного висловлювання є true. Якщо ми приберемо крапку з кінця рядка, результат буде вже false.

Аналогічно екрануються й інші спеціальні символи.

Var str = "x+y=.n*m=/,co\la"; var reg = /x\+y=\.n\*m=\/,co\\la/; alert(reg.test(str)); // true

Тут ми зробили екранування символів плюс (\+), точки (\.), зірочки (\*), звичайного слеша (\/) та зворотного слеша (\\\). Зверніть увагу, що зворотний сліш у рядку пишеться двома зворотними слішами. І екранується він у регулярному вираженні, також за допомогою двох зворотних слішів.

Якщо ми за допомогою alert, виведемо рядок із змінної str, то замість двох зворотних слішів побачимо лише один.

Аналогічно екрануються всі ті символи, які вказані в довіднику, в розділі мета-символи.

І на цьому, мабуть, усі. З цієї маленької статті, Ви вже знаєте як екранувати спеціальні символи і як їх використовувати для складання регулярних виразів.

Завдання
  • Припустимо, нам потрібно перевірити на відповідність, такий рядок "Я виграв 400 $". Напишіть регулярний вираз, який перевіряв наявність символу долара в кінці рядка. Перевірте рядок на відповідність.
    • Переклад
    • Tutorial

    SQL ін'єкції, підробка міжсайтових запитів, пошкоджений XML… Страшні, страшні речі, від яких ми всі хотіли б захиститися, та ось тільки знати б чому це все відбувається. Ця стаття пояснює фундаментальне поняття, яке стоїть за цим: рядки і обробка рядків усередині рядків.

    Основна проблема Це лише текст. Так, просто текст – ось вона основна проблема. Практично все у комп'ютерній системі представлено текстом (який, своєю чергою, представлений байтами). Хіба що одні тексти призначені для комп'ютера, інші для людей. Але і ті, і ті, все ж таки залишаються текстом. Щоб зрозуміти, про що я говорю, наведу невеликий приклад:
    Homo Sapiens Suppose, є це англійський текст, який I don't wanna translate inRussia
    Не повірите: це текст. Деякі люди називають його XML, але це просто текст. Можливо, він не підійде для показу вчителю англійської мови, але це все ще просто текст. Ви можете роздрукувати його на плакаті і ходити з ним на мітинги, ви можете написати його у листі до своєї мами… це - текст.

    Тим не менш, ми хочемо, щоб певні частини цього тексту мали якесь значення для нашого комп'ютера. Ми хочемо, щоб комп'ютер міг отримати автора тексту і сам текст окремо, щоб з ним можна було щось зробити. Наприклад, перетворити вищезгадане на це:
    Повідомляється, що це є англійський текст, який я ' t wanna translate in Russian by Homo Sapiens
    Звідки комп'ютер знає, як це зробити? Ну, тому що ми дуже до речі обернули певні частини тексту спеціальними словами в кумедних дужках, як, наприклад, в. Оскільки ми зробили це, ми можемо написати програму, яка шукала б ці певні частини, витягувала текст і використовувала його для якогось нашого власного винаходу.

    Іншими словами, ми використовували певні правила в нашому тексті, щоб позначити якесь особливе значення, яке хтось, дотримуючись тих самих правил, міг би використати.
    Гаразд, це все не так уже й важко зрозуміти. А якщо ми хочемо використовувати ці кумедні дужки, які мають якесь особливе значення, у нашому тексті, але без використання цього самого значення?.. Приблизно так:
    Homo Sapiens< n and y >
    Символи "" не є нічим особливим. Вони можуть законно використовуватися будь-де, в будь-якому тексті, як у прикладі вище. Але як же наша ідея про спеціальні слова, типу? Чи це означає, що теж є якимось ключовим словом? У XML – можливо так. А можливо, ні. Це неоднозначно. Оскільки комп'ютери не дуже справляються з неоднозначностями, щось у результаті може дати непередбачений результат, якщо ми не розставимо самі всі точки над i і не усунемо неоднозначності.
    Вирішити цю дилему можна, замінивши неоднозначні символи чимось однозначним.
    Homo Sapiens Basic math tells us that if x< n and y >n, x cannot be larger than y.
    Тепер текст має стати повністю однозначним. "".
    Технічне визначення цього - екрануванняМи уникаємо спеціальних символів, коли не хочемо, щоб вони мали своє особливе значення.
    escape |iˈskāp| [No obj. ] вирватися волю [ with obj. ] не помітити / не згадати [...] [ with obj. ] IT: причина бути інтерпретованим по-різному [...]
    Якщо певні символи або послідовності символів у тексті мають особливе значення, то повинні бути правила, що визначають, як вирішити ситуації, коли ці символи повинні використовуватися без особливого значення. Або, іншими словами, екранування відповідає на запитання: "Якщо ці символи такі особливі, то як мені використовувати їх у своєму тексті?".
    Як можна було помітити на прикладі вище, амперсанд (&) - це теж спеціальний символ. Але що робити, якщо ми хочемо написати


    Якщо ваші користувачі будуть хорошими і добрими, то вони розміщуватимуть цитати старих філософів, а повідомлення матимуть приблизно такий вигляд:

    Posted by Plato on January 2, 15:31

    I am said to have said "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.


    Якщо користувачі будуть розумниками, то вони, мабуть, говоритимуть про математику, і повідомлення будуть такі:

    Posted by Pascal на Листопад 23, 04:12

    Basic math tells us that if x< n and y >n, x cannot be larger than y.


    Хм... Знову ці осквернителі наших дужок. Ну, з технічної точки зору, вони можуть бути неоднозначними, але браузер простить нам це, правда?


    Добре, СТОП, що за біса? Якийсь жартівник ввів javascript теги на ваш форум? Будь-хто, хто дивиться на це повідомлення на вашому сайті, зараз завантажує і виконує скрипти в контексті вашого сайту, які можуть зробити не знати що. А це не є добре.

    Не слід розуміти буквально У вищезгаданих випадках ми хочемо якимось чином повідомити нашу БД або браузеру, що це просто текст, ти з ним нічого не роби! Іншими словами, ми хочемо "видалити" особливі значення всіх спеціальних символів та ключових слів з будь-якої інформації, наданої користувачем, бо ми йому не довіряємо. Що ж робити?

    Що? Що кажеш, хлопче? Ах, ти кажеш, "екранування"? І ти абсолютно правий, візьми печінку!
    Якщо ми застосуємо екранування до даних користувача до об'єднання їх із запитом, то проблема вирішена. Для наших запитів до БД це буде щось на зразок:
    $name = $_POST["name"]; $name = mysql_real_escape_string($name); $query = "SELECT phone_number FROM users WHERE name = "$name""; $result = mysql_query($query);
    Просто один рядок коду, але тепер більше ніхто не може зламати нашу базу даних. Давайте знову подивимося як виглядатимуть SQL-запити, залежно від введення користувача:
    Alex
    SELECT phone_number FROM users WHERE name = "Alex"
    Mc"Donalds
    SELECT phone_number FROM users WHERE name = "Mc"Donalds
    Joe"; DROP TABLE users; --
    SELECT phone_number FROM users WHERE name = "Joe"; DROP TABLE users; --"
    mysql_real_escape_string без розбору поміщає косу межу перед усім, у чого може бути якесь особливе значення.


    Ми застосовуємо функцію htmlspecialchars до всіх даних користувача, перш ніж вивести їх. Тепер повідомлення шкідника виглядає так:

    Posted by JackTR on July 18, 12:56


    Зверніть увагу, що значення, отримані від користувачі, насправді не "ушкоджені". Будь-який браузер парсить цей як HTML і виведе на екран все у правильній формі.

    Що повертає нас до... Все вищезгадане демонструє проблему, характерну для багатьох систем: текст у тексті має бути екранований, якщо передбачається, що він не повинен мати спеціальних символів. Поміщаючи текстові значення SQL, вони мають бути екрановані за правилами SQL. Поміщаючи текстові значення HTML, вони мають бути екрановані за правилами HTML. Поміщаючи текстові значення (назва технології), вони повинні бути екрановані за правилами (назва технології). Ось і все. Для повноти картини Є, звичайно, інші способи боротьби з введенням користувача, який повинен або не повинен містити спеціальні символи:
    • Validation
      Ви можете перевірити, чи відповідає введення користувача певної заданої специфікації. Якщо Ви потребуєте введення числа, а користувач вводить щось інше, програма повинна повідомити про це і скасувати введення. Якщо це правильно організувати, немає ніякого ризику схопити " DROP TABLE users " там, де, передбачалося, користувач введе " 42 " . Це дуже практично, щоб уникнути HTML/SQL-ін'єкцій, т.к. часто потрібно прийняти текст вільного формату, який може містити "підкили". Зазвичай валідацію використовують на додаток до інших заходів.
    • Sanitization
      Ви можете так само "тишком" видалити будь-які символи, які вважаєте небезпечними. Наприклад, просто видалити щось схоже на HTML-тег, щоб уникнути додавання на ваш форум. Проблема в тому, що можна видалити цілком законні частини тексту.
      Prepared SQL statements
      Є спеціальні функції, які роблять те, чого ми й домагалися: змушують БД зрозуміти різницю між самим SQL-запросом та інформацією, наданої користувачами. У РНР вони виглядають приблизно так:
      $stmt = $pdo->prepare("SELECT phone_number FROM users WHERE name = ?"); $stmt->execute($_POST["name"]);
      При цьому відправка відбувається у два етапи, чітко розмежовуючи запит та змінні. БД може спочатку зрозуміти структуру запиту, та був заповнити його значеннями.

    • У реальному світі все це використовується разом для різних ступенів захисту. Ви повинні використовувати перевірку допустимості (валідацію), щоб бути впевненим, що користувач вводить коректні дані. Потім ви можете сканувати введені дані (але не зобов'язані). Якщо користувач явно намагається втюхати вам якийсь скрипт, ви можете просто видалити його. Потім, ви завжди, завжди повинні екранувати дані користувача перш, ніж помістити їх в SQL-запит (це ж стосується і HTML).

    3.1 Екранування спецсимволів

    Перш ніж передавати значення змінних форми в SQL-запити, необхідно спеціальним чином екранувати деякі символи (зокрема, апостроф), наприклад, поставити перед ними зворотний слеш. Для вставки призначена функція:

    mysql_escape_string()

    string mysql_escape_string(string $str)

    Функція схожа на іншу функцію addslashes(), проте вона додає слеші перед повним набором спеціальних символів. Практика показує, що для текстових даних можна використовувати функцію addslashes() замість mysql_escape_string(). Багато скриптах так і робиться.

    За стандартом MySQL екранування піддаються символи, які в РНР записуються так: "\х00", "\n", "\г", "\", """, "" і "\х1А".

    Це число містить символ з нульовим ASCII-кодом, а тому mysql_escape_string() допустимо застосовувати не тільки для текстових, але також і для бінарних даних. Можна, наприклад, вважати змінну GIF-зображення (функція file_get_contents ()), а потім вставити його в базу даних, попередньо проекранувавши всі спецсимволи. При вилученні картинка виявиться у тому вигляді, у якому вона була спочатку.

    Екранування символів це лише спосіб запису коректних SQL-виражень, не більше. З даними нічого не відбувається, і вони зберігаються в базі без додаткових слеш - так, як виглядали спочатку, ще до екранування.

    З використанням mysql_escape_string()код попереднього запиту виглядає так:

    "DELETE FROM table WHERE name="".mysql_escape_string($name).""");

    Це довго, незграбно та некрасиво.


    3.2 Шаблони запитів та placeholders

    Розглянемо інше рішення.

    Замість явного екранування та вставки змінних у запит на їх місце поміщають спеціальні маркери (placeholders, "охоронці місця"), які зазвичай виглядають як?.

    Ті самі значення, які будуть підставлені замість них, передаються окремо додатковими параметрами.

    З використанням гіпотетичної функції mysql_qwo, код якої буде представлений нижче, попередній запит може бути переписаний так:

    mysql_qw ("DELETE FROM table WHERE name=?", $name);

    Запит став коротшим і краще захищений: тепер ми вже при написанні коду не зможемо випадково пропустити виклик функції mysql_escape_string() і, таким чином, потрапити на прийом хакера. Усі перетворення відбуваються автоматично, усередині функції.

    У лістингу lib_mysql_qw.php міститься найпростіша реалізація функції mysql_qw() (qw - від англ. query wrapper, "обгортка для запиту").

    Є також бібліотека lib/Placeholder.php, що забезпечує значно потужнішу підтримку мови placeholders: http://dklab.ru/chicken/30.html.

    У більшості ситуацій можливостей, що надаються функцією mysql_qw(), виявляється достатньо.

    Лістинг lib_mysql_qw.php



    Подібні публікації