C# 在存储过程中使用分隔参数是否危险?
我的C#面是这样的:C# 在存储过程中使用分隔参数是否危险?,c#,sql,sql-server,C#,Sql,Sql Server,我的C#面是这样的: if(Request.QueryString["ValuesFromUser"]!=null) { ValuesFromUser_ = Request["ValuesFromUser"]; } DataTable dtle = new DataTable(); SqlDataAdapter sqda; sqda = new SqlDataAdapter("Checkforuserinput", Connection); SqlParameter SQP = sqd
if(Request.QueryString["ValuesFromUser"]!=null)
{
ValuesFromUser_ = Request["ValuesFromUser"];
}
DataTable dtle = new DataTable();
SqlDataAdapter sqda;
sqda = new SqlDataAdapter("Checkforuserinput", Connection);
SqlParameter SQP = sqda.SelectCommand.Parameters.Add("@arg", SqlDbType.VarChar);
SQP.Direction = ParameterDirection.Input;
SQP.Value = "ValuesFromUser_";
sqda.Fill(dtle );
ALTER FUNCTION [dbo].[SplitDelimiterString] (@StringWithDelimiter VARCHAR(8000), @Delimiter VARCHAR(8))
RETURNS @ItemTable TABLE (Item VARCHAR(8000))
AS
BEGIN
DECLARE @StartingPosition INT;
DECLARE @ItemInString VARCHAR(8000);
SELECT @StartingPosition = 1;
--Return if string is null or empty
IF LEN(@StringWithDelimiter) = 0 OR @StringWithDelimiter IS NULL RETURN;
WHILE @StartingPosition > 0
BEGIN
--Get starting index of delimiter .. If string
--doesn't contain any delimiter than it will returl 0
SET @StartingPosition = CHARINDEX(@Delimiter,@StringWithDelimiter);
--Get item from string
IF @StartingPosition > 0
SET @ItemInString = SUBSTRING(@StringWithDelimiter,0,@StartingPosition)
ELSE
SET @ItemInString = @StringWithDelimiter;
--If item isn't empty than add to return table
IF( LEN(@ItemInString) > 0)
INSERT INTO @ItemTable(Item) VALUES (@ItemInString);
--Remove inserted item from string
SET @StringWithDelimiter = SUBSTRING(@StringWithDelimiter,@StartingPosition +
LEN(@Delimiter),LEN(@StringWithDelimiter) - @StartingPosition)
--Break loop if string is empty
IF LEN(@StringWithDelimiter) = 0 BREAK;
END
RETURN
END
用户将传递一些参数,如“user1、user2、user3”
在我的sql端:
Create PROC [dbo].[Checkforuserinput] @arg VARCHAR(50)= 'All'
As
Select *
from UserData
where User in (SELECT *
FROM SplitDelimiterString(@Arg, ','))
SplitDelimiterString函数类似于:
if(Request.QueryString["ValuesFromUser"]!=null)
{
ValuesFromUser_ = Request["ValuesFromUser"];
}
DataTable dtle = new DataTable();
SqlDataAdapter sqda;
sqda = new SqlDataAdapter("Checkforuserinput", Connection);
SqlParameter SQP = sqda.SelectCommand.Parameters.Add("@arg", SqlDbType.VarChar);
SQP.Direction = ParameterDirection.Input;
SQP.Value = "ValuesFromUser_";
sqda.Fill(dtle );
ALTER FUNCTION [dbo].[SplitDelimiterString] (@StringWithDelimiter VARCHAR(8000), @Delimiter VARCHAR(8))
RETURNS @ItemTable TABLE (Item VARCHAR(8000))
AS
BEGIN
DECLARE @StartingPosition INT;
DECLARE @ItemInString VARCHAR(8000);
SELECT @StartingPosition = 1;
--Return if string is null or empty
IF LEN(@StringWithDelimiter) = 0 OR @StringWithDelimiter IS NULL RETURN;
WHILE @StartingPosition > 0
BEGIN
--Get starting index of delimiter .. If string
--doesn't contain any delimiter than it will returl 0
SET @StartingPosition = CHARINDEX(@Delimiter,@StringWithDelimiter);
--Get item from string
IF @StartingPosition > 0
SET @ItemInString = SUBSTRING(@StringWithDelimiter,0,@StartingPosition)
ELSE
SET @ItemInString = @StringWithDelimiter;
--If item isn't empty than add to return table
IF( LEN(@ItemInString) > 0)
INSERT INTO @ItemTable(Item) VALUES (@ItemInString);
--Remove inserted item from string
SET @StringWithDelimiter = SUBSTRING(@StringWithDelimiter,@StartingPosition +
LEN(@Delimiter),LEN(@StringWithDelimiter) - @StartingPosition)
--Break loop if string is empty
IF LEN(@StringWithDelimiter) = 0 BREAK;
END
RETURN
END
对于SQL注入,此代码是安全的还是有风险的
或者我应该使用这个:
Create PROC [dbo].[Checkforuserinput] @arg VARCHAR(50)= 'All'
As
declare @query nvarchar(max)
set @query = 'Select * from UserData where User in ('+@Arg+')'
EXECUTE sp_executesql @query
根据您的SQLServer版本,您可能需要考虑将表值参数传递给存储过程。 表值参数提供了一种将多行数据从客户端应用程序封送到SQL Server的简单方法,无需多次往返或特殊的服务器端逻辑来处理数据。您可以使用表值参数封装客户端应用程序中的数据行,并在单个参数化命令中将数据发送到服务器。SqlParameter通过使用AddWithValue方法填充,SqlDbType设置为Structured
以下链接提供了一个良好的概述:我看不出split函数存在任何可预见的问题,但传递表值参数会更有效 SQL C# 编写一个helper函数,将任何
IEnumerable(string)
写入SQL Server能够理解的DataTable
public static class SqlExtensions
{
public static DataTable ToSqlArray(this IEnumerable<string> collection)
{
var dt = new DataTable("ArrayOfString");
dt.Columns.Add(new DataColumn("Item", typeof(string)));
foreach(var item in collection)
{
var row = dt.NewRow();
row[0] = item;
dt.Rows.Add(row);
}
return dt;
}
}
分割功能肯定更好。最坏的情况是,它应该在您的C#命令调用中抛出异常。第二种方法适合SQL注入。另外,请注意,如果合适的话,您可以将该函数的结果进行内部联接,而不是使用子查询(这会快得多,但如果您的数据允许的话,它可能会得到多行),没有任何东西可以阻止某人将类似于
user1,'drop table UserData
(或类似的内容)的内容传递到查询中。快速浏览一下,您的分割函数看起来很好。