Как я могу разделить пунктуацию от строки?

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

  • строка
  • номер
  • идентификатор
  • ключевое слово синтаксиса.

и подготовленные операторы охватывают только 2 из них

. Но иногда нам приходится делать наш запрос еще более динамичным, добавляя операторы или идентификаторы также. Таким образом, нам понадобятся разные методы защиты.

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

$orders  = array("name","price","qty"); //field names
$key     = array_search($_GET['sort'],$orders)); // see if we have such a name
$orderby = $orders[$key]; //if not, first one will be set automatically. smart enuf :)
$query   = "SELECT * FROM `table` ORDER BY $orderby"; //value is safe

Однако есть еще один способ защитить идентификаторы - экранирование. Пока вы указываете идентификатор, вы можете избежать обратных звонков внутри, удвоив их.

В качестве еще одного шага мы можем заимствовать поистине блестящую идею использования некоторого заполнителя (прокси для представления фактического значения в запросе) из подготовленных операторов и изобретать местозаполнитель другого типа - заполнителя идентификатора .

Итак, чтобы сделать длинный рассказ коротким: это заполнитель, не подготовленное заявление можно рассматривать как серебряную пулю.

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

Тем не менее, есть проблема с ключевыми словами синтаксиса SQL (например, AND, DESC и т. д.), но белый список - единственный подход в этом случае.

Обновить

Несмотря на то, что существует общее согласие в отношении наилучшей практики защиты SQL-инъекций, все еще существует множество плохих методов. И некоторые из них слишком глубоко укоренены в умах пользователей PHP. Например, на этой самой странице есть (хотя и невидимые для большинства посетителей) более 80 удаленных ответов - все они удалены сообществом из-за плохого качества или продвижения плохих и устаревших практик. Хуже того, некоторые из плохих ответов не удаляются, а скорее процветают.

Например, там (1) являются (2) еще (3) many (4) отвечает (5) , в том числе второй наиболее ответный ответ , предлагающий вам ручное стирание строки - устаревший подход, который оказался небезопасным.

Или есть несколько лучший ответ, который предлагает только другой метод форматирования строк и даже может похвастаться им как окончательной панацеей. Хотя, конечно, это не так. Этот метод не лучше обычного форматирования строки, но он сохраняет все свои недостатки: он применим только к строкам и, как и любое другое ручное форматирование, по существу является необязательной, необязательной мерой, склонной к человеческой ошибке любого рода.

Я думаю, что все это из-за одного очень старого суеверия, поддержанного такими авторитетами, как OWASP или PHP manual , который провозглашает равенство между тем, что «ускользает» "и защита от SQL-инъекций.

Независимо от того, что написано в руководстве по PHP, *_escape_string ни в коем случае не делает данные безопасными и никогда не предназначались. Помимо бесполезности для любой части SQL, отличной от строки, ручное экранирование неверно, поскольку оно является ручным, как автоматическое.

И OWASP делает это еще хуже, подчеркивая, что пользовательский вход пользователя является совершенно бессмысленным: таких слов в контексте защиты от инъекций не должно быть. Каждая переменная потенциально опасна - независимо от источника! Или, другими словами, каждая переменная должна быть должным образом отформатирована для включения в запрос - независимо от источника. Это вопрос назначения. В тот момент, когда разработчик начинает отделять овец от коз (думая, является ли какая-то конкретная переменная «безопасной» или нет), он делает свой первый шаг к катастрофе. Не говоря уже о том, что даже формулировка предполагает, что в точке входа происходит массовое ускорение, напоминающее очень волшебную функцию кавычек - уже презренный, устаревший и удаленный.

Итак, в отличие от любого «экранирования» подготовленные операторы мера, которая действительно защищает от SQL-инъекции (если применимо).

Если вы все еще не уверены, вот пошаговое объяснение, которое я написал, The Hitchhiker's Guide на SQL Injection Prevention , где я подробно объяснил все эти вопросы и даже составил раздел, полностью посвященный плохим практикам и их раскрытию.

64
задан Community 23 May 2017 в 12:31
поделиться

9 ответов

new string(myCharCollection.Where(c => !char.IsPunctuation(c)).ToArray());
102
ответ дан Hath 24 November 2019 в 15:42
поделиться

Почему не просто:

string s = "sxrdct?fvzguh,bij.";
var sb = new StringBuilder();

foreach (char c in s)
{
   if (!char.IsPunctuation(c))
      sb.Append(c);
}

s = sb.ToString();

использование RegEx обычно медленнее, чем простые символьные операции. И те операции LINQ похожи на излишество мне. И Вы не можете использовать такой код в.NET 2.0...

18
ответ дан Hades32 24 November 2019 в 15:42
поделиться

Принятие "лучше всего" означает "самый простой", я предлагаю использовать что-то вроде этого:

String stripped = input.replaceAll("\\p{Punct}+", "");

Этот пример для Java, , но все достаточно современные механизмы Regex должны поддерживать это (или что-то подобное).

Редактирование: Осведомленная о Unicode версия была бы этим:

String stripped = input.replaceAll("\\p{P}+", "");

первая версия только смотрит на знаки пунктуации, содержавшиеся в ASCII.

13
ответ дан Joachim Sauer 24 November 2019 в 15:42
поделиться

Можно использовать regex.replace метод:

 replace(YourString, RegularExpressionWithPunctuationMarks, Empty String)

, Так как это возвращает строку, Ваш метод будет выглядеть примерно так:

 string s = Regex.Replace("Hello!?!?!?!", "[?!]", "");

можно ли заменить" [?!]" с чем-то более сложным, если Вы хотите:

(\p{P})

Это должно найти любую пунктуацию.

8
ответ дан Anton 24 November 2019 в 15:42
поделиться

Базирующийся от идеи GWLLOSA, я смог придумать в высшей степени ужасный, но работа:

string s = "cat!";
s = s.ToCharArray().ToList<char>()
      .Where<char>(x => !char.IsPunctuation(x))
      .Aggregate<char, string>(string.Empty, new Func<string, char, string>(
             delegate(string s, char c) { return s + c; }));
4
ответ дан Tom Ritter 24 November 2019 в 15:42
поделиться

Большая часть braindead простого способа сделать его использовала бы string.replace

другим путем, я воображу, regex.replace, и имейте свое регулярное выражение со всеми соответствующими знаками пунктуации в нем.

3
ответ дан TheTXI 24 November 2019 в 15:42
поделиться

Вот немного отличающийся подход с помощью linq. Мне нравится AviewAnew, но это избегает Агрегата

        string myStr = "Hello there..';,]';';., Get rid of Punction";

        var s = from ch in myStr
                where !Char.IsPunctuation(ch)
                select ch;

        var bytes = UnicodeEncoding.ASCII.GetBytes(s.ToArray());
        var stringResult = UnicodeEncoding.ASCII.GetString(bytes);
1
ответ дан JoshBerke 24 November 2019 в 15:42
поделиться
#include<string>
    #include<cctype>
    using namespace std;

    int main(int a, char* b[]){
    string strOne = "H,e.l/l!o W#o@r^l&d!!!";
    int punct_count = 0;

cout<<"before : "<<strOne<<endl;
for(string::size_type ix = 0 ;ix < strOne.size();++ix)   
{   
    if(ispunct(strOne[ix])) 
    {
            ++punct_count;  
            strOne.erase(ix,1); 
            ix--;
    }//if
}
    cout<<"after : "<<strOne<<endl;
                  return 0;
    }//main
0
ответ дан 24 November 2019 в 15:42
поделиться

Описывает намерение, самый простой для чтения (ИМХО) и наиболее эффективный:

 s = s.StripPunctuation();

для реализации:

public static class StringExtension
{
    public static string StripPunctuation(this string s)
    {
        var sb = new StringBuilder();
        foreach (char c in s)
        {
            if (!char.IsPunctuation(c))
                sb.Append(c);
        }
        return sb.ToString();
    }
}

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

11
ответ дан 24 November 2019 в 15:42
поделиться
Другие вопросы по тегам:

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