Имя безопасного динамического столбца в динамическом LINQ

Я пытаюсь создать динамическое предложение WHERE с помощью LINQ. У меня есть рабочий пример, но я беспокоюсь, что он не защищен от SQL-инъекций.

Следующий код LINQ:

var oQuery = _db.People.Where("FirstName.Contains(@0)", "kev");

производит следующий SQL:

SELECT 
[Extent1].[FirstName] AS [[FirstName], 
[Extent1].[LastName] AS [[LastName], 
WHERE [Extent1].[[FirstName] LIKE '%kev%'

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

var oQuery = _db.People.Where("@0.Contains(@1)", strSelectedColumn,"kev");

Но это производит следующий SQL:

  SELECT 
    [Extent1].[FirstName] AS [[FirstName], 
    [Extent1].[LastName] AS [[LastName], 
    WHERE N'FirstName' LIKE N'%kev%'}

что, очевидно, неверно и дает 0 строк в результате, потому что он сравнивает 2 строки. Используя параметры, LINQ, вероятно, просто введет параметры в виде строки при построении запроса и не будет использовать эффективное имя столбца во время построения.

Решение состоит в том, чтобы просто использовать следующий запрос LINQ:

var oQuery = _db.People.Where(strSelectedColumn + ".Contains(@0)", "kev");

Но это приводит к возможному небезопасному SQL, который можно использовать для внедрения SQL.

Как я могу использовать свои динамические столбцы LINQ и при этом получать безопасный код?


person Kevin Cloet    schedule 05.02.2014    source источник
comment
Как вы предлагаете имена полей, из которых пользователь может выбирать?   -  person Gert Arnold    schedule 06.02.2014
comment
Они не могут выбирать динамически, я использую его для фильтрации столбцов в сетке, и я хотел бы повторно использовать сетку на разных страницах.   -  person Kevin Cloet    schedule 06.02.2014


Ответы (2)


Эта линия

var oQuery = _db.People.Where(strSelectedColumn + ".Contains(@0)", "kev");

генерировать безопасный код SQL, потому что перед генерацией SQL-запроса динамический linq анализирует строковое выражение и создает деревья выражений. Поэтому, если в strSelectedColumn недействительном столбце, динамическое linq вызывает исключение синтаксического анализа, прежде чем генерировать запрос sql.

когда вы используете это

var oQuery = _db.People.Where("@0.Contains(@1)", strSelectedColumn,"kev");

ты получаешь

WHERE N'FirstName' LIKE N'%kev%'

поскольку вы не проверяете значение поля, вы пытаетесь проверить значение строковых параметров.

person Grundy    schedule 14.02.2014
comment
У вас есть какой-либо источник или ссылка на то, как LINQ подтверждает, что это допустимый столбец? Если они делают что-то вроде ЕСЛИ существует... со строкой, вы все равно можете использовать небезопасный SQL - person Kevin Cloet; 14.02.2014
comment
@KevinCloet, вы можете увидеть в источнике DynamicLinq все что касается разбора - person Grundy; 14.02.2014
comment
@KevinCloet, в двух словах, исключение возникает при создании деревьев выражений, когда вы пытаетесь получить свойство из класса, где это свойство отсутствует - person Grundy; 14.02.2014

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

// user input: "abc';evil statement here"

strSelectedColumn = new string(strSelectedColumn.Where(c => char.IsLetter(c)).ToArray());
// abcevilstatementhere

var oQuery = _db.People.Where(strSelectedColumn + ".Contains(@0)", "kev");
person user247702    schedule 05.02.2014