Как создавать динамические и безопасные запросы - PullRequest
6 голосов
/ 10 ноября 2008

«Статический» запрос - это тот, который всегда остается неизменным. Например, кнопка «Теги» в Stackoverflow или кнопка «7 дней» в Digg. Короче говоря, они всегда отображаются на конкретный запрос к базе данных, поэтому вы можете создавать их во время разработки.

Но я пытаюсь выяснить, как выполнять «динамические» запросы, когда пользователь в основном диктует, как запрос к базе данных будет создаваться во время выполнения. Например, в Stackoverflow вы можете комбинировать теги и фильтровать сообщения по своему выбору. Это динамический запрос, хотя и очень простой, поскольку вы можете комбинировать его с миром тегов. Более сложный пример, если вы можете объединить теги и пользователей.

Прежде всего, когда у вас есть динамический запрос, кажется, что вы больше не можете использовать API подстановки, чтобы избежать внедрения SQL, так как элементы запроса будут зависеть от того, что пользователь решил включить в запрос. Я не вижу, как еще построить этот запрос, кроме как с помощью строки append.

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

Как мне реализовать нечто подобное?

Ответы [ 4 ]

2 голосов
/ 10 ноября 2008

Первое правило заключается в том, что пользователям разрешается указывать значения в выражениях SQL, но не синтаксис SQL . Весь синтаксис запроса должен быть буквально указан вашим кодом, а не пользователем. Значения, указанные пользователем, могут быть предоставлены SQL в качестве параметров запроса. Это наиболее эффективный способ ограничения риска внедрения SQL.

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

Я работал над классом PHP под названием Zend_Db_Select, который предоставляет API, чтобы помочь с этим. Если вам нравится PHP, вы можете посмотреть на этот код для идей. Он не обрабатывает любые мыслимые мысли, но делает многое.

Некоторые другие платформы баз данных PHP имеют аналогичные решения.

1 голос
/ 10 ноября 2008

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

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

Когда число столбцов в критериях фильтрации произвольно, но мало, рассмотрите возможность использования различных статических запросов для каждой возможности.

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

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

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

0 голосов
/ 10 ноября 2008

Если бы вы использовали python для доступа к вашей базе данных, я бы предложил вам использовать модель системы Django . Существует много похожих API для Python и для других языков (особенно в ruby ​​на рельсах). Я экономлю так много времени, избегая необходимости напрямую общаться с базой данных с помощью SQL.

С пример ссылки :

#Model definition
class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __unicode__(self):
        return self.name

Использование модели (это фактически оператор вставки)

from mysite.blog.models import Blog
b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
b.save()

Запросы становятся намного сложнее - вы передаете объект запроса и можете добавлять к нему фильтры / элементы сортировки. Когда вы, наконец, готовы использовать запрос, Django создает SQL-статистику, которая отражает все способы, которыми вы настраивали объект запроса. Я думаю, что это очень мило.

Другие преимущества этой абстракции

  • Django может создавать ваши модели в виде таблиц базы данных с внешними ключами и ограничениями
  • Поддерживаются многие базы данных (Postgresql, Mysql, sql lite и т. Д.)
  • DJango анализирует ваши шаблоны и создает автоматический админ-сайт из них.
0 голосов
/ 10 ноября 2008

Ну, варианты должны быть сопоставлены с чем-то.

Строка SQL-запроса CONCAT не является проблемой, если вы все еще используете параметры для параметров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...