Поддержка неэмулируемых подготовленных операторов из MS SQL Server через PHP в Linux

Резюме

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


сценарий

Я размещаю сайт на Linux, который подключается к Microsoft SQL Server с FreeTDS версии 0.91, в частности, с использованием FreeTDS dblib, Я установил tds версия до 7.4 для подключения к базе данных, и я использую объект PDO PHP.

Согласно документации FreeTDS, 4.2 не поддерживает подготовленные заявления:

TDS 4.2 имеет ограничения

  • Только ASCII, конечно.
  • RPC не поддерживается.
  • BCP не поддерживается.
  • поля varchar ограничены 255 символами. Если ваша таблица определяет более длинные поля, они будут усечены.
  • динамические запросы (также называемые подготовленными операторами) не поддерживаются.

Однако ничто не указывает на то, что 7.4 не поддерживает подготовленные операторы, что дает мне разумную уверенность, что они, по крайней мере, не вызовут ошибку драйвера.

PDO PHP поддерживает определенные атрибуты соединения через PDO::setAttribute(), Я заинтересован в PDO::ATTR_ERRMODE установить все ошибки как исключения, и PDO::ATTR_EMULATE_PREPARES заставить базу данных делать подготовленные операторы, если они совместимы.


вопрос

При тестировании соединения я получаю следующую ошибку:

Ошибка базы данных: SQLSTATE[IM001]: драйвер не поддерживает эту функцию: драйвер не поддерживает настройку атрибутов

Не имея возможности установить PDO::ATTR_EMULATE_PREPARES Я не могу гарантировать, что база данных фактически выполняет подготовленные операторы, как и предполагалось.

Есть ли способ изменить мой подход или есть альтернативный подход, чтобы гарантировать, что подготовленные операторы выполняются безопасно на MS SQL Server из Linux?

1 ответ

Решение

Решение

использование ODBC вместо dblib, что обеспечивает полную функциональность PDO. Обратите внимание, что существует две возможные конфигурации ODBC: автономный ODBC и FreeTDS с драйвером ODBC. Исходя из моего опыта, чтобы установить набор символов для соединения, это должно быть сделано через FreeTDS с использованием драйвера ODBC, что делает объединенную конфигурацию предпочтительной.


Настройка ODBC

Я просмотрел множество различных публикаций Stackru и различные источники документации в Интернете о том, как правильно установить ODBC. Я вытащил свое решение из смеси следующих трех ссылок:

Ниже приведен список шагов, которые я использовал для настройки ODBC с помощью FreeTDS в системе на основе Debian.

TDS 8.0 поддерживает подготовленные заявления.

ПРИМЕЧАНИЕ: не будет поддерживать SET NAMES a или же SET CHARSET a на связи; наборы символов должны быть определены с использованием комбинированной конфигурации путем установки атрибута FreeTDS. При использовании автономного драйвера ODBC по умолчанию кодировка ASCII, который дал странные результаты. Смотрите мой другой пост для примеров возможных проблем.

Установите требуемые пакеты:

sudo apt-get установить freetds-bin freetds-common unixodbc tdsodbc php5-odbc

  • freetds-bin предоставляет FreeTDS, а также tsql а также isql (используется для отладки позже).
  • freetds-common был уже установлен в системе, но не включает два средства отладки. Установка freetds-bin позднее, после того, как конфиг был определен, проблема не возникает.
  • unixodbc это драйвер ODBC
  • tdsodbc предоставляет протокол TDS для ODBC
  • php5-odbc модуль php для используемых драйверов ODBC Обратите внимание, что ваша версия PHP может отличаться от моей.

Настроить автономный unixODBC

Настройки драйвера ODBC в /etc/odbcinst.ini:

[odbc]
Description     = ODBC driver
Driver          = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
Setup           = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so 
UsageCount      = 1

Создайте общесистемную конфигурацию имени источника данных в /etc/odbc.ini:

[datasourcename]
 Driver         = odbc
 Description    = Standalone ODBC
 Server         = <IP or hostname>
 Port           = <port>
 TDS_Version    = 8.0

Сконфигурируйте unixODBC и FreeTDS:

Настройки драйвера ODBC в /etc/odbcinst.ini:

[odbc]
Description     = ODBC driver
Driver          = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
Setup           = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so 
UsageCount      = 1

Создайте общесистемную конфигурацию имени источника данных в /etc/odbc.ini:

[datasourcename]
Driver          = FreeTDS_odbc
Description     = Uses FreeTDS configuration settings defined in /etc/freetds/freetds.conf
Servername      = datasourcename
TDS_Version     = 8.0

Добавьте конфигурацию имени источника данных ODBC в FreeTDS в /etc/freetds/freetds.conf:

[datasourcename]
    host = <IP or hostname>
    port = <port>
    client charset = UTF-8
    tds version = 8.0
    text size = 20971520
    encryption = required

ВАЖНО: убедитесь, что файлы odbc доступны для чтения процессом, который их читает. Если вы используете свой веб-сервер, используя www-data пользователь, они должны иметь соответствующие разрешения для чтения этих файлов!

Теперь вы можете установить набор символов подключения в freetds.conf и подключиться к базе данных с PDO как

$pdo = new PDO('odbc:datasourcename');

Тестирование:

использование tsql проверить, что FreeTDS настроен и может подключаться к базе данных.

tsql -S имя источника данных -U имя пользователя -P пароль

использование isql проверить правильность подключения ODBC.

isql -v datasourcename имя пользователя пароль

Связать ODBC с PHP:

Добавить модуль ODBC PHP в php.ini добавив следующее:

extension = odbc.so

Обратите внимание, что вы php.ini Местоположение будет зависеть от того, какой веб-сервер вы используете. использование <?php phpinfo(); ?> и просмотрите его через веб-сервер, чтобы найти его местоположение.

Перезапустите Apache

РЕДАКТИРОВАТЬ: Добавлена ​​информация о возможностях набора символов драйвера, так как я столкнулся с проблемами с автономной конфигурацией ODBC, где он игнорировал бы любую попытку изменить набор символов соединения.

Другие вопросы по тегам