在不使用 QUOTENAME 的情况下正确转义 SQL Server 中的分隔标识符

2023-11-21

除了将标识符(表、视图、列)用双引号括起来以及标识符名称中存在的“双引号”之外,代码还必须执行其他操作吗?参考文献将不胜感激。

我继承了一个具有自定义对象关系映射 (ORM) 系统的代码库。 SQL 无法在应用程序中编写,但 ORM 最终仍必须生成 SQL 并将其发送到 SQL Server。所有标识符都用双引号引起来。

string QuoteName(string identifier) 
{ 
    return "\"" + identifier.Replace("\"", "\"\"") + "\"";
}

如果我正在构建这个动态 SQLin SQL,我会使用内置的 SQL Server QUOTENAME 函数:

declare @identifier nvarchar(128);
set @identifier = N'Client"; DROP TABLE [dbo].Client; --';

declare @delimitedIdentifier nvarchar(258);
set @delimitedIdentifier = QUOTENAME(@identifier, '"');

print @delimitedIdentifier;
-- "Client""; DROP TABLE [dbo].Client; --"

我还没有找到任何关于如何在 SQL Server 中转义带引号的标识符的明确文档。我已经发现分隔标识符(数据库引擎)我还看到了这个计算器问题关于消毒。

如果必须调用 QUOTENAME 函数只是为了引用标识符,那么 SQL Server 的流量就很大,这是不必要的。

ORM 似乎在 SQL 注入方面经过了深思熟虑。它是用 C# 编写的,早于 nHibernate 端口和实体框架等。所有用户输入都是使用 ADO.NET SqlParameter 对象发送的,它只是我在这个问题中关心的标识符名称。这需要在 SQL Server 2005 和 2008 上运行。


更新于2010-03-31

虽然应用程序不应允许用户在查询中输入标识符名称,但 ORM 通过其用于 ORM 样式读取和自定义查询的查询语法来实现。我试图最终阻止所有可能的 SQL 注入攻击的是 ORM,因为与所有应用程序代码相比,它非常小且易于验证。

一个简单的查询接口示例:

session.Query(new TableReference("Client")
    .Restrict(new FieldReference("city") == "Springfield")
    .DropAllBut(new FieldReference("first_name"));

ADO.NET 发送以下查询:

exec sp_executesql N'SELECT "T1"."first_name" 
FROM "dbo"."Client" AS "T1" 
WHERE "T1"."city" = @p1;', 
N'@p1 nvarchar(30)', 
N'Springfield';

也许思考一下 nHibernate 查询语言 (HQL) 中类似的情况会有所帮助:

using (ISession session = NHibernateHelper.OpenSession())
{
    Client client = session
        .CreateCriteria(typeof(Client))  \\ <-- TableReference in example above
        .Add(Restrictions.Eq("city", "Springfield"))  \\ <-- FieldReference above
        .UniqueResult<Client>();
    return client;
}

也许我应该看看 nHibernate 如何保护输入。


Your QuoteName函数需要检查长度,因为 T-SQL QUOTENAME 函数指定了它返回的最大长度。使用你的例子:

String.Format(@"declare @delimitedIdentifier nvarchar(258);
set @delimitedIdentifier = {0};", QuoteName(identifier));

If QuoteName(identifier)长度超过 258 个字符,分配给它时会被静默截断@delimitedIdentifier。当这种情况发生时,你就有了可能性@delimitedIdentifier以不当方式逃脱。

MSDN 文章“Microsoft 安全软件开发人员”Bala Neerumalla 更深入地解释了这个主题。该文章还包含我发现的最接近“有关如何在 SQL Server 中转义带引号的标识符的权威文档”的内容:

转义机制只是将右方括号的出现次数加倍。您不需要对其他字符执行任何操作,包括左方括号。

这是我当前使用的 C# 代码:

/// <summary>
/// Returns a string with the delimiters added to make the input string
/// a valid SQL Server delimited identifier. Brackets are used as the
/// delimiter. Unlike the T-SQL version, an ArgumentException is thrown
/// instead of returning a null for invalid arguments.
/// </summary>
/// <param name="name">sysname, limited to 128 characters.</param>
/// <returns>An escaped identifier, no longer than 258 characters.</returns>
public static string QuoteName(string name) { return QuoteName(name, '['); }

/// <summary>
/// Returns a string with the delimiters added to make the input string
/// a valid SQL Server delimited identifier. Unlike the T-SQL version,
/// an ArgumentException is thrown instead of returning a null for
/// invalid arguments.
/// </summary>
/// <param name="name">sysname, limited to 128 characters.</param>
/// <param name="quoteCharacter">Can be a single quotation mark ( ' ), a
/// left or right bracket ( [] ), or a double quotation mark ( " ).</param>
/// <returns>An escaped identifier, no longer than 258 characters.</returns>
public static string QuoteName(string name, char quoteCharacter) {
    name = name ?? String.Empty;
    const int sysnameLength = 128;
    if (name.Length > sysnameLength) {
        throw new ArgumentException(String.Format(
            "name is longer than {0} characters", sysnameLength));
    }
    switch (quoteCharacter) {
        case '\'':
            return String.Format("'{0}'", name.Replace("'", "''"));
        case '"':
            return String.Format("\"{0}\"", name.Replace("\"", "\"\""));
        case '[':
        case ']':
            return String.Format("[{0}]", name.Replace("]", "]]"));
        default:
            throw new ArgumentException(
                "quoteCharacter must be one of: ', \", [, or ]");
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在不使用 QUOTENAME 的情况下正确转义 SQL Server 中的分隔标识符 的相关文章

  • 计算树中值的总和(递归查询)

    我在表员工 id name parentid 中有树结构 并且该表可以嵌套 employees 与另一个具有列 id employeeid quantity 的 Sales 表是一对多关系 每个员工都有销售数量 我想计算每个员工以及儿童员工
  • 内联表值 UDF 能否优于 SELECT 列列表中的等效标量 UDF?

    这个问题源于SQLServer 为什么要避免表值用户定义函数 https stackoverflow com questions 1081057 sqlserver why avoid table valued user defined f
  • 仅基于月份和年份的 SQL Server 日期比较

    我无法确定仅根据月份和年份比较 SQL 中的日期的最佳方法 我们根据日期进行计算 由于计费是按月进行的 因此该月的日期会造成更多障碍 例如 DECLARE date1 DATETIME CAST 6 15 2014 AS DATETIME
  • 将 SQL Server varBinary 数据转换为字符串 C#

    我需要帮助弄清楚如何转换来自SQL服务器表列设置为varBinary 最大 转换为字符串以便将其显示在标签中 这是在C 我正在使用数据读取器 我可以使用以下方式提取数据 var BinaryString reader 1 我知道该列包含之前
  • 为什么MERGE语句的目标表不允许启用规则?

    我们有一个使用以下 SQL 更新数据库的过程 IF NOT EXISTS SELECT FROM Target Table WHERE Target Table ID BEGIN INSERT END ELSE BEGIN UPDATE E
  • 如何在没有聚合函数的情况下在sql server中创建枢轴查询

    我正在使用 MS SQL SERVER 2008 并且有以下数据 select from account PERIOD ACCOUNT VALUE 2000 Asset 205 2000 Equity 365 2000 Profit 524
  • 在 Dockerfile 中切换到 root 用户

    我运行了这个命令 docker pull mcr microsoft com mssql server 2019 latest 然后我创建了一个 dockerfile 来使用此容器映像作为另一个容器的基础映像 escape FROM mcr
  • 如何获取 dm_exec_sql_text 的参数值

    我正在运行以下语句来查看 sql server 中正在执行哪些查询 select from sys dm exec requests r cross apply sys dm exec sql text r sql handle where
  • 从另一台计算机连接到 SQL Server

    我正在使用 C 连接到网络上另一台计算机上的 SQL Server 但收到一条异常消息 用户 用户名 登录失败 但是服务器日志状态表明使用 Windows 身份验证的用户连接成功 我的连接字符串是 Data Source ipaddress
  • SQL Server 全文的自定义断字器

    有谁知道如何为 SQL Server 2005 创建自定义分词系统 我更喜欢用 C 编写它 我需要能够搜索 c f 等术语 但 字符是英语 英国 分词器组件中的分词器 不能以任何其他方式更改 我发现以下文章提供了不完整的示例 缺少 IWor
  • 如何检查Azure SQL数据库中是否已存在数据库用户

    我的新客户计划使用 Azure 托管 SQL 数据库服务 我正在使用 dacpac 来部署数据库 在 dacpac 中 我有一个部署后脚本 用于创建 sql 用户 如下所示 IF NOT EXISTS SELECT name FROM sy
  • NOLOCK 和 UNCOMMITTED 之间有什么区别

    我使用 SQL Server 2012 我写了两个查询 但是它们之间有什么不同NOLOCK and UnCommitted SELECT lastname firstname FROM HR Employees with READUNCOM
  • SQL最近的命令?微软SQL

    我只是编写一个查询来查看我的客户数据库并列出他们下了多少订单等 我正在努力添加到此查询中的是只显示该电子邮件的最新 OrderID 有任何想法吗 这是我的查询 select top 1000 BuyerEMail COUNT HowMany
  • 在 SQL Profiler 中查找特定 LINQ 查询的巧妙技巧

    由于有时会创建疯狂的 SQL 因此分析 LINQ 查询及其执行计划尤为重要 我经常发现我需要跟踪特定的查询 但很难在查询分析器中找到 我经常在有大量正在运行的事务的数据库 有时是生产服务器 上执行此操作 因此仅打开 Profiler 是没有
  • 如何使用jdbc驱动编写事务?

    我想使用 jdbc 编写一个事务java 我尝试过这个简单的交易 BEGIN TRANSACTION NL GO NL UPDATE table SET col test where id 1010 NL GO NL COMMIT 我尝试过
  • 有没有适用于 Eclipse 的 SQL 格式化插件?

    我在网上没有找到任何标准的开源 sql 格式化程序 eclipse 插件 我正在使用日食太阳神 我可以找到编辑 gt 格式化SQL但这似乎不起作用 找到一个在http ventralnet blogspot in 2010 11 sql b
  • System.IndexOutOfRangeException:索引超出了数组的范围[重复]

    这个问题在这里已经有答案了 我正在开发一个 ATM 软件作为家庭作业 我想知道今天处理的交易总量 为此我编写了以下代码 public decimal getDayTransaction int accountid string date s
  • 需要在SQL Server 2012中自动递增字符串

    考虑 SQL Server 2012 中的表 789 0000000 上面的数字在 SQL Server 2012 中将被视为字符串 但每当我更新记录时 我都需要增加到 1 例如 当我更新记录 1 时 它应该增加到789 0000001 当
  • SQL Server 文本数据类型最大长度 = 65,535?

    我正在使用的软件使用文本字段来存储 XML 根据我的在线搜索 文本数据类型应该包含 2 31 1 个字符 目前 SQL Server 每次都会将 XML 截断为 65 535 个字符 我知道这是由 SQL Server 引起的 因为如果我直
  • 我可以采取哪些措施来提高 SQL Server 中纯用户定义函数的性能?

    我制作了一个简单但计算相对复杂的 UDF 用于查询很少更改的表 在典型用法中 该函数会在一个非常小的参数域上从 WHERE 子句中多次调用 如何才能更快地使用 UDF 我的想法是应该有某种方式告诉 SQL Server 我的函数使用相同的参

随机推荐

  • 捕获所有未处理的 javascript 承诺拒绝

    我想捕获 javascript Promise 中发生的所有未处理的异常 拒绝 有没有一个好的方法可以在不添加的情况下捕获它们 catch 在 Promise 链的每一端 如果忘记添加此错误 错误将自动消失 Google Chrome 中的
  • Qt Creator JS 中有哪些可用的 JS 对象:变量扩展?

    Qt Creator 的向导和配置设置支持变量扩展 包括 JavaScript 表达式的计算 例如这C 类向导文件模板包含 JS Cpp openNamespaces Class Cpp似乎是一个全局对象 这些定义在 Qt Creator
  • 引导模式内的日期选择器中的月份选择在 Firefox 中不起作用

    如果日期选择器中的月份选择位于引导模式内 则它在 FireFox 中不起作用
  • 为什么我们在java中需要用户定义的类加载器

    为什么tomcat有自己的类加载器 用户定义的类加载器有什么好处 它隔离部署到容器中的各种Web应用程序 也就是说 Web 应用程序的行为不会受到部署 取消 部署另一个 Web 应用程序的影响 每个 Web 应用程序只能看到自己的类 而看不
  • 当窗口恢复时,C# 中是否会引发事件?

    在 C NET 中恢复窗口时是否会引发任何事件 我注意到激活窗口时会引发一个事件 但我找不到正在恢复的窗口的相应事件 例如从最大化或最小化状态 如果您不喜欢使用表格WindowState属性并且不想保留指示表单先前状态的标志 您可以在稍低的
  • 如何获取调用错误的位置?

    我正在寻找替代品loch 及其预处理器 因为它不能使用 ghc 7 进行编译 具体来说 如果error被调用然后我想尽可能方便地弄清楚它是从哪里调用的 行号和堆栈跟踪会很好 您可以使用 xcRTS 选项 如所述这一页 您需要使用分析支持来编
  • 创建带有自定义 URL、标题和图像的 Facebook 分享按钮

    Facebook 曾经允许在 Facebook 分享按钮中自定义参数 但现在不起作用 我需要的是创建一个 Facebook 分享按钮 该按钮将具有自定义标题 网址 图像 描述等 它无法使用元标记来完成 因为单个页面上有多个分享按钮 每个应该
  • 为什么我的 Eclipse 控制台中有多个 Angular 语言服务器选项卡

    这些天我经常打开 PyDev 透视图并在 Eclipse 中进行 Python 编程 当我从 IDE 运行 Python 程序并检查控制台的输出时 我发现我不仅有 Python 运行的输出 而且我现在还计数了 4 个 Angular 语言服
  • 如何在项目上下文之外包含 Maven 模块?

    我希望在某种全局项目目录中有一个模块 以便我可以将该模块包含在使用该通用代码的所有其他项目中 但我怎样才能告诉内行父母pom包含并编译这个全局共享模块 以下不起作用 svn MyGlobalProject project commons p
  • ko.toJSON() 可以处理日期吗?

    我在 ASP NET MVC 页面上使用 KnockoutJS 我正在使用 ajax 通过调用将表单保留回服务器ko toJSON viewModel 然后使用 jQuery 将结果发送回服务器 视图模型上的所有属性均已成功序列化 但 Ja
  • 导入 com.google.android.gms.* 时出错;

    我正在尝试实施该解决方案link 需要导入这些 import com google android gms common ConnectionResult import com google android gms common Googl
  • 在 github actions yml 文件中创建 Minio(S3) 容器

    我正在尝试创建一个 Minio S3 容器 以便我可以在 github 上运行我的测试套件作为操作 我目前有以下内容 name Run Tests on push branches master pull request branches
  • 如何更改 Apache Tomcat Web 服务器端口号 [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 如何更改 Apache Tomcat Web 服务器默认端口号 我正在 JSP 中开发一个 Web 应用程序 出于某种目的 我需要更改 tomcat 访问端口 有没有可能 简单 您可
  • 如何在 LibreOffice 中安装或激活 PyUno?

    如何让 Python 任何 Python 了解 LibreOffice 中的 PyUno 当我做 import uno python says that it knows no module uno This question came u
  • 使用远程图像创建 CycleTile

    我见过许多展示 CycleTile 实际应用的示例 但这些示例都使用了本地图像 是否可以在应用程序首次运行后设置这些图像并将 CycleTile 指向远程图像 或者 如果我确实需要先将这些保存到手机中 如何让 CycleTile 引用它们
  • Linux 上哪些 C++ IDE 的“智能感知”能力与 Visual Studio 相当或更好? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 管道中有一些基于 Linux 的 C 项目 我应该选择哪种 IDE 来提供某种与纯 Visual Studio 即没有 Visual Assist
  • 在java中使用response.sendRedirect方法发送Post请求

    我想用java发送一个post请求 我已经看到使用 Http 客户端发送请求的示例 但我想使用 sendRedirect 方法 对于前 我想使用 post 请求发送这些参数 因此 这些参数对任何人都不可见 同时我需要将我的网址重定向到该网址
  • 如何在Tensorflow 2.0中通过Xavier规则进行权重初始化?

    TF 2 0恰巧干掉了contrib图书馆 因此 所有的好东西都喜欢tf contrib conv2d or tf contrib layers variance scaling initializer消失了 也就是说 您认为在 TF2 0
  • MEF 和单独的接口组装导致“每个类的接口”

    我特别熟悉 DI IoC 和 MEF 我有一个 Web 应用程序 它有两种类型的部分 也许有一天会更多 这些部分由需要访问整个环境的接口定义 该应用程序有一个由 MEF 组成的列表 其中包含每种类型的具体实现 环境包括 几个存储库 当前的申
  • 在不使用 QUOTENAME 的情况下正确转义 SQL Server 中的分隔标识符

    除了将标识符 表 视图 列 用双引号括起来以及标识符名称中存在的 双引号 之外 代码还必须执行其他操作吗 参考文献将不胜感激 我继承了一个具有自定义对象关系映射 ORM 系统的代码库 SQL 无法在应用程序中编写 但 ORM 最终仍必须生成