Linux 上的 MS SQL Server 通过 PHP 提供非模拟预准备语句支持

2024-01-09

Summary

我正在尝试使用准备好的语句来停止 SQL 注入,但无法找到保证其正常工作所需的支持。


Scenario

我在 Linux 上托管一个站点,该站点使用 FreeTDS 版本 0.91 连接到 Microsoft SQL Server,特别是使用 FreeTDSdblib。我已经设置了tds用于数据库连接的版本为 7.4,并且正在使用 PHPPDO http://php.net/manual/en/book.pdo.php object.

根据FreeTDS 文档 http://www.freetds.org/userguide/choosingtdsprotocol.htm、4.2不支持prepared statements:

TDS 4.2 有局限性

  • 当然,仅限 ASCII。
  • 不支持 RPC。
  • 不支持 BCP。
  • varchar 字段的长度限制为 255 个字符。如果您的表定义 较长的字段,它们将被截断。
  • 不支持动态查询(也称为准备好的语句)。

然而,没有任何迹象表明 7.4 不支持准备好的语句,这给了我合理的信心,它们至少不会引发驱动程序错误。

PHP 的 PDO 通过以下方式支持连接特定属性PDO::setAttribute() http://php.net/manual/en/pdo.setattribute.php。 我对感兴趣PDO::ATTR_ERRMODE将所有错误设置为异常,以及PDO::ATTR_EMULATE_PREPARES强制数据库执行准备好的语句(如果兼容)。


Issue

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

数据库错误:SQLSTATE[IM001]:驱动程序不支持此功能:驱动程序不支持设置属性

无法设置的情况下PDO::ATTR_EMULATE_PREPARES,我无法保证数据库实际上按预期执行准备好的语句。

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


Solution

Use ODBC代替dblib,它提供了 PDO 的全部功能。 请注意,ODBC 有两种可能的配置:独立的ODBC https://web.archive.org/web/20200504140812/http://www.freetds.org:80/userguide/odbcinionly.htm and 带有 ODBC 驱动程序的 FreeTDS https://web.archive.org/web/20200504140959/http://www.freetds.org:80/userguide/odbcombo.htm。根据我的经验,要设置连接的字符集,必须使用 ODBC 驱动程序通过 FreeTDS 来完成,这使得组合配置更可取。


ODBC 设置

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

  • unixODBC 设置文档 http://www.unixodbc.org/doc/FreeTDS.html
  • FlipperPA的回答设置 FreeTDS https://stackoverflow.com/questions/33341510/how-to-install-freetds-in-linux(顺便用ODBC完成)
  • Benny Hill对此的回答FreeTDS 的设置问题 https://stackoverflow.com/questions/13066716/freetds-not-using-its-config

以下是我用来配置的步骤列表ODBC using FreeTDS在基于 Debian 的系统上。

TDS 8.0 支持准备好的语句。

注意:不支持SET NAMES a or SET CHARSET a在连接上;需要通过设置 FreeTDS 属性使用组合配置来定义字符集。使用独立 ODBC 驱动程序默认字符集为ASCII,这给出了奇怪的结果。看我的其他帖子 https://stackoverflow.com/questions/279170/utf-8-all-the-way-through获取可能问题的示例。

安装需要的包:

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

  • freetds-bin提供 FreeTDS,以及tsql and isql(用于后续调试)。
  • freetds-common系统上已安装,但不包括这两个调试工具。安装中freetds-bin在定义配置后的晚些时候,不会出现任何问题。
  • unixodbc是 ODBC 驱动程序
  • tdsodbc为 ODBC 提供 TDS 协议
  • php5-odbc是使用 ODBC 驱动程序的 php 模块。请注意,您的 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');

Testing:

Use tsql检查 FreeTDS 是否已配置并且可以连接到数据库。

tsql -S 数据源名称 -U 用户名 -P 密码

Use isql检查 ODBC 是否正确连接。

isql -v 数据源名称 用户名 密码

将 ODBC 与 PHP 链接:

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

扩展名=odbc.so

请注意,您的php.ini位置取决于您使用的网络服务器。 使用<?php phpinfo(); ?>并通过网络服务器查看它以找到其位置。

重新启动阿帕奇

编辑: 添加了有关驱动程序字符集功能的信息,因为我遇到了独立 ODBC 配置的问题,它将忽略任何更改连接字符集的尝试。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 上的 MS SQL Server 通过 PHP 提供非模拟预准备语句支持 的相关文章

  • 使用 Vala 和 GLib 的正则表达式

    有没有一个函数 比如http php net manual en function preg match all php http php net manual en function preg match all php 使用 GLibh
  • 如何比较两个字符串的大小写和变音符号不敏感?

    我有两根弦 字符串 1 塞巴斯蒂安 字符串 2 塞巴斯蒂安 我想通过忽略 重音 字符来比较这两个字符串 谁能知道这个逻辑吗 提前致谢
  • PHP 如果不存在,则从字符串中删除 ','

    我正在运行这段代码 stmt pdo conn gt prepare SELECT from admin where support emails support emails and logged logged and disabled
  • PHP 相等变量

    我想知道是否有任何方法可以检查大量变量是否相等 如果我只有几个变量 我可以这样做 if a b a c b c 但是 如果我有 20 个变量 则需要一些时间来编写所有组合 还有其他方法吗 if count array unique arra
  • PHP mkdir() 和 fopen() 不起作用 - 权限问题? umask问题?

    以下 PHP 脚本无法创建目录 它也将无法创建文件 当目录已经存在时 ini set error reporting E ALL define ABSPATH SERVER DOCUMENT ROOT echo ABSPATH br br
  • 在 PHP 中将十进制/双精度/浮点值与 PDO 绑定的最佳方法是什么?

    看来类常量只涵盖PDO PARAM BOOL PDO PARAM INT and PDO PARAM STR用于绑定 您只是将十进制 浮点 双精度值绑定为字符串还是有更好的方法来处理它们 MySQLi 允许使用 d 类型表示 double
  • 如何在 Laravel 代码中使用 Artisan 命令?

    如何在我的 php caode Ex 中使用 Artisan 命令行 php artisan version to 您可以从控制器调用 Artisan 命令 如下所示 calling of migrate install Artisan c
  • 在 Apache 服务器上将特定的 .htm 页面处理为 .php [重复]

    这个问题在这里已经有答案了 我正在为 Apache 服务器编程 并且只需要将一个特定的 html 页面 例如 first htm 作为 PHP 脚本进行处理 可以设置吗 SetHandler http httpd apache org do
  • 设置 Vim 背景颜色

    当我尝试更改背景颜色时 vimrc或者直接在 Vim 中使用以下命令 set background dark 这根本不影响我的背景 也没有light选项 不过 当我运行 gvim 时 看起来还不错 有没有办法在不更改 Konsole 设置的
  • tar.gz 和 tgz 是同一个东西吗? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我创建了 tgz 文件tar czvf filecommand then 我最终得到了一个 tgz 文件 我想知道它和tar gz 之间的
  • laravel 5.4 在请求验证之前修改数据[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我有我的自定义请求 它扩展了 Backpack CrudController 现在我想重写 ValidatesWhenResolv
  • 在存储过程结束时显式删除本地临时表有什么好处?

    考虑以下伪 T SQL 代码 由存储过程执行 CREATE TABLE localTable
  • 如何使用 PHP 从 MySQL 检索特定值?

    好吧 我已经厌倦了 过去一周我花了大部分空闲时间试图解决这个问题 我知道 SQL 中的查询已更改 但我无法弄清楚 我能找到的所有其他帖子似乎都已经过时了 如果有人能帮助我 我将非常感激 我想做的就是使用手动输入数据库的唯一 密码 来检索行的
  • 在 MacO 和 Linux 上安装 win32com [重复]

    这个问题在这里已经有答案了 我的问题很简单 我可以安装吗win32com蟒蛇API pywin32特别是 在非 Windows 操作系统上 我一直在Mac上尝试多个版本pip install pywin32 都失败了 下面是一个例子 如果你
  • 在Linux中创建可执行文件

    我计划做的一件事是编写 非常简单的 Perl 脚本 并且我希望能够在不从终端显式调用 Perl 的情况下运行它们 我明白 要做到这一点 我需要授予他们执行权限 使用 chmod 执行此操作非常简单 但它似乎也是一个稍微费力的额外步骤 我想要
  • 与 array_intersect 相反?

    是否有一个内置函数可以获取数组 1 中不存在于数组 2 中的所有成员 我知道如何以编程方式执行此操作 只是想知道是否有一个内置函数可以执行相同的操作 所以请不要提供代码示例 这听起来像是一份工作array diff http www php
  • 如何使用 PHP 获取列中的所有值?

    我一直在到处寻找这个问题 但仍然找不到解决方案 如何从 mySQL 列中获取所有值并将它们存储在数组中 例如 表名称 客户 列名称 ID 名称 行数 5 我想获取此表中所有 5 个名称的数组 我该如何去做呢 我正在使用 PHP 我试图 SE
  • Spring Boot MSSQL Kerberos 身份验证

    目前在我的春季靴子中application properties文件中 我指定以下行来连接到 MSSql 服务器 spring datasource url jdbc sqlserver localhost databaseName spr
  • 从一个sql服务器选择到另一个sql服务器?

    我想将一台服务器 Data Old S1 中的一个表 T1 在 DB1 中 中的数据选择到另一台服务器 Data Latest S2 中的另一个表 T2 在 DB2 中 中的数据 我怎样才能做到这一点 请注意服务器的命名方式 查询也应该考虑
  • 如何获取 URL 中未知的 $_GET 值的数组?

    我正在使用一个在线购物车 它接受订购的商品并通过 URL 将其唯一 ID 传递到 process php 页面 所以 URL 看起来像这样 process php code 1 231 code 2 532 code 3 342 Anoth

随机推荐