Поддержка неэмулируемых подготовленных операторов из 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. Я вытащил свое решение из смеси следующих трех ссылок:
- документация по настройке unixODBC
FlipperPA
ответ на настройку FreeTDS (кстати, сделано с ODBC)Benny Hill
ответ на этот вопрос установки с FreeTDS
Ниже приведен список шагов, которые я использовал для настройки 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
это драйвер ODBCtdsodbc
предоставляет протокол TDS для ODBCphp5-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, где он игнорировал бы любую попытку изменить набор символов соединения.