在Linux上通过PHP从MS SQL Server获得非仿真准备语句支持

摘要

我正在尝试使用预准备语句来停止SQL注入,但我无法找到我需要的支持以保证它正常工作.

脚本

我在Linux上托管一个站点,该站点连接到具有FreeTDS版本0.91的Microsoft SQL Server,特别是使用FreeTDS的dblib.我已将tds版本设置为7.4以进行数据库连接,并使用PHPPDO对象.

根据FreeTDS documentation,4.2不支持准备好的声明:

TDS 4.2 has limitations

  • ASCII only, of course.
  • RPC is not supported.
  • BCP is not supported.
  • varchar fields are limited to 255 characters. If your table defines
    longer fields, they’ll be truncated.
  • dynamic queries (also called prepared statements) are not supported.

但是没有任何迹象表明7.4不支持预处理语句,这给了我合理的信心,他们至少不会抛出驱动程序错误.

PHP的PDO通过PDO::setAttribute()支持特定于连接的属性.
我感兴趣的是PDO :: ATTR_ERRMODE将所有错误设置为异常,而PDO :: ATTR_EMULATE_PREPARES则强制数据库在兼容时执行预准备语句.

问题

测试连接时,收到以下错误:

Database error: SQLSTATE[IM001]: Driver does not support this function: driver does not support setting attributes

如果无法设置PDO :: ATTR_EMULATE_PREPARES,我无法保证数据库实际上是按预期执行预准备语句.

无论如何都要修改我的方法,或者是否有替代方法
保证准备好的语句在Linux上的MS SQL Server上安全执行?

最佳答案 解

使用ODBC而不是dblib,它提供PDO的全部功能.
请注意,ODBC有两种可能的配置:standalone ODBCFreeTDS with ODBC driver.根据我的经验,要设置连接的字符集,必须使用ODBC驱动程序通过FreeTDS完成,使组合配置更可取.

ODBC安装程序

我在网上搜索了许多不同的StackOverflow帖子和各种文档资源,了解如何正确安装ODBC.我从以下三个参考文献的混合中提取了我的解决方案:

> unixODBC setup documentation
> FlipperPA对setting up FreeTDS的回答(顺便完成了ODBC)
> Benny Hill对setup issue with FreeTDS的回答

下面是我在基于Debian的系统上使用FreeTDS配置ODBC的步骤列表.

TDS 8.0支持预准备语句.

注意:在连接上不支持SET NAMES a或SET CHARSET a;需要通过设置FreeTDS属性使用组合配置来定义字符集.使用独立的ODBC驱动程序将charset默认为ASCII,这会产生奇怪的结果.有关可能出现的问题的示例,请参阅我的other post.

安装require包:

sudo apt-get install freetds-bin freetds-common unixodbc tdsodbc
php5-odbc

> freetds-bin提供FreeTDS,以及tsql和isql(稍后用于调试).
> freetds-common已经安装在系统上,但不包括两个调试工具.定义配置后,在以后安装freetds-bin会导致问题.
> unixodbc是ODBC驱动程序
> tdsodbc为ODBC提供TDS协议
> php5-odbc是使用ODBC驱动程序的php模块.请注意,您的php版本可能与我的不同.

配置独立unixODBC

/etc/odbcinst.ini中的ODBC驱动程序设置:

[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:

/etc/odbcinst.ini中的ODBC驱动程序设置:

[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

在/etc/freetds/freetds.conf中将ODBC数据源名称配置添加到FreeTDS:

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

IMPORTANT: make sure that the odbc files are readable by the process
that will be reading them. If you are running your webserver using a
www-data user, they must have the proper permissions to read those
files!

您现在可以在freetds.conf中设置连接字符集,并使用PDO连接到数据库

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

测试:

使用tsql检查FreeTDS是否已配置并可以连接到数据库.

tsql -S datasourcename -U username -P password

使用isql检查ODBC是否正确连接.

isql -v datasourcename username password

链接ODBC与PHP:

通过添加以下内容将ODBC PHP模块添加到php.ini:

extension = odbc.so

请注意,php.ini位置将取决于您使用的Web服务器.
使用<?php phpinfo(); ?>并通过网络服务器查看它以查找其位置. 重启Apache 编辑:
添加了有关驱动程序字符集功能的信息,因为我遇到了独立ODBC配置的问题,它会忽略任何更改连接字符集的尝试.

点赞