首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何防止SQL注入

如何防止SQL注入
EN

Stack Overflow用户
提问于 2011-01-27 04:21:30
回答 3查看 4.7K关注 0票数 5

我使用的是存储过程。为了节省时间,我做了一些通用的过程,使用动态sqlin命令进行更新。这样的通用过程是:

代码语言:javascript
运行
复制
CREATE PROCEDURE [dbo].[SetField]
 @company_id uniqueidentifier,
 @id bigint,
 @field_code nvarchar(50),
 @value nvarchar(50)
AS
BEGIN
 DECLARE @field_name nvarchar(50)
 SET @field_name = NULL
 SELECT @field_name=field_name
 FROM dbo.FIELD_DEFINITION
 WHERE field_code=@field_code

 IF @field_name IS NOT NULL
 BEGIN

  IF @value IS NULL OR @value=''
  BEGIN
   SET @value='NULL'
  END
  ELSE
  BEGIN
   IF @field_code='START_DATE' OR @field_code='END_DATE'
   BEGIN
    SET @value = CONVERT(datetime, @value ,103)
   END
   SET @value=''''+@value+''''
  END

  DECLARE @sql nvarchar(1000)
  SET @sql = 'UPDATE dbo.TABLE '+
     'SET '+@field_name+'='+@value+' '+
     'WHERE company_id=''' + CAST(@company_id as nvarchar(36)) + ''' AND '+
     'id='+CAST(@id as nvarchar)
  EXEC(@sql)
 END
END

如何使用此代码防止sql注入?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-01-27 04:30:29

关于SQL注入需要记住的重要方面是,如果可能的话,您永远不应该将用户提供的值直接嵌入到您的SQL中。这并不意味着您不能使用动态sql (尽管如果您不使用它肯定会使事情变得更容易),但它有时确实变得更加危险。

在您的特定示例中,您可以保留除@field_name之外的所有内容的参数化。不幸的是,这必须直接嵌入到SQL中;其他所有内容都可以作为参数再次传递,所以不必担心它们的内容。

在此特定示例中,您可以执行的最安全的操作如下:

代码语言:javascript
运行
复制
if(exists (select 1 from INFORMATION_SCHEMA.Columns where TABLE_NAME = 'Table' and TABLE_SCHEMA = 'dbo' and COLUMN_NAME = @fieldName))
begin
    DECLARE @sql nvarchar(1000)
    SET @sql = 'UPDATE dbo.TABLE '+
       'SET ' + QUOTENAME(@field_name) + '=@value ' + 
       'WHERE company_id=@company_id AND '+
       'id=@id'

    exec sp_executesql @sql,N'@id bigint, @company_id uniqueidentifier, @value nvarchar(50)',@id,@company_id,@value
end

这会做两件事:

  1. 它验证表中是否确实存在具有该名称的列。如果用户要将任何其他SQL语句嵌入到该字段中,则此检查将失败,并且不会执行该语句。您也可以调用raiseerror来报告错误,但我将把这项工作留给您。
  2. 它将字段名括在方括号中,这样包含空格或保留字的字段名将不会中断语句。这对您来说可能不是问题,但如果您自己生成SQL,这始终是一个很好的做法。
票数 5
EN

Stack Overflow用户

发布于 2011-01-27 04:37:03

你说过:

为了节省时间,我做了一些通用的过程,使用动态sql来更新

如果你先问一下,我们可以节省时间,并建议这样做...

代码语言:javascript
运行
复制
UPDATE
    dbo.TABLE
SET
    Field1 = CASE WHEN @field_name = 'Field1' THEN @value ELSE Field1 END,
    Field2 = CASE WHEN @field_name = 'Field2' THEN @value ELSE Field2 END,
    Field3 = CASE WHEN @field_name = 'Field3' THEN @value ELSE Field3 END,
    ...
    Fieldn = CASE WHEN @field_name = 'Fieldn' THEN @value ELSE Fieldn END
WHERE
    company_id = @company_id AND id = @id
票数 6
EN

Stack Overflow用户

发布于 2011-01-27 04:24:47

在调用SP之前,我会开始寻找防止sql注入攻击的方法。使用从querystring或表单数据拼凑而成的动态SQL字符串时要小心。使用SqlCommand对象。

编辑:作为对这条评论的回应,这里很好地解释了参数化查询( SQL )如何帮助防止SqlCommand注入。

来自http://forums.asp.net/t/1568268.aspx

SQL占位符- @Id -已经成为硬编码...The的一部分。在运行时,查询字符串提供的值与硬编码的SQL一起传递给数据库,数据库将在尝试将参数值绑定到ProductID字段时检查该字段。这确保了一定程度的强类型。如果参数值不是数据库字段的正确类型(字符串或超出字段类型范围的数字),则数据库将无法将其转换为正确的类型并将其拒绝。如果目标字段数据类型是字符串(char、nvarchar等),参数值将被自动“字符串化”,包括转义单引号。它不会构成要执行的SQL语句的一部分。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4809608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档