C# 当字符串有数字时,过程中断
我已在SQL Server中编写了此过程:C# 当字符串有数字时,过程中断,c#,asp.net,sql-server,visual-studio-2010,C#,Asp.net,Sql Server,Visual Studio 2010,我已在SQL Server中编写了此过程: ALTER proc [dbo].[cazacliente2] (@vbusca nvarchar(60), @bo int) as if @bo= 1 begin select idcliente, nome, endere, tel, pedido from Vw_Conscliente where nome like @vbusca end if @bo = 2 beg
ALTER proc [dbo].[cazacliente2]
(@vbusca nvarchar(60), @bo int)
as
if @bo= 1
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where nome like @vbusca
end
if @bo = 2
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where endere like @vbusca
end
if @bo = 3
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where tel like @vbusca
end
if @bo = 4
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where pedido like @vbusca
end
asp.net中的以下代码:
{
string valorC = "%" + TextBox1.Text + "%"; numo = DropDownList1.SelectedValue;
string valorB = valorC.Replace(" ", "%");
switch (numo)
{
case "Nome": num3 = 1; break; case "Endereço": num3 = 2; break ;
case "Telefone": num3 = 3 ; break; case "Pedido": num3 = 4; break ;
}
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "cazacliente2";
SqlParameter valor = new SqlParameter("@vbusca", SqlDbType.NVarChar);
SqlParameter num = new SqlParameter("@bo",SqlDbType.Int );
valor.Value = valorB ; num.Value = num3 ;
cmd.Parameters.Add(valor); cmd.Parameters.Add(num);
if (conex1.State == ConnectionState.Closed)
{ conex1.Open(); }
cmd.Connection = conex1;
try
{
GridView1.EmptyDataText = "Nao se" + numo.ToString() +"encontraron registros";
GridView1.DataSource = cmd.ExecuteReader();
GridView1.DataBind();
}
catch (Exception ex)
{ throw ex; }
finally
{ conex1.Close(); }
}
当我传递字符串afonso pena时,过程返回所有数据,但当我传递afonso 60时,它返回一个错误,当我传递一个不在数据库中的名称时,它再次中断,这就像部件捕获不起作用一样。我会将通配符移到TSQL,而不是C。这样,您可以独立测试它 您的定义显示最大长度为60
@vbusca nvarchar(60)
从C传递给SQL的参数是否大于该值?您应该在VisualStudio中查看断点上的局部变量,以确认这不是真的
此外,替换参数中的空格意味着参数中的逻辑字只需按任意顺序匹配即可。这是你想要的吗
“阿方索60”与“阿方索什么时候去商店买60美元的牛奶”相匹配
查看MSDN了解通配符的用法:
我在下面使用了动态SQL,因为它减少了总体代码大小
示例代码更改:
ALTER PROC [dbo].[cazacliente2] (@vbusca nvarchar(32), @bo int) AS
BEGIN
-- Local variables
DECLARE @statement VARCHAR(MAX);
DECLARE @field VARCHAR(MAX);
DECLARE @expression VARCHAR(MAX);
-- Make the expression (exact match of @vbusca)
SET @expression = '%' + REPLACE(@vbusca,'''', '''''') + '%';
-- Optional way (match words in @vbusca in order)
-- SET @expression = '%' + REPLACE(REPLACE(@vbusca,'''', ''''''), ' ', '%') + '%'
-- Which field
SELECT @field =
CASE @bo
WHEN 1 then 'nome'
WHEN 2 then 'endere'
WHEN 3 then 'tel'
WHEN 4 then 'pedido'
ELSE 'nome'
END;
-- Make up the dynamic SQL
SET @statement = 'select idcliente, nome, endere, tel, pedido ' +
' from Vw_Conscliente where ' + @field + ' like ' + @expression;
-- Execute the SQL statement
EXEC @statement;
END;
我将在将来编写的任何动态TSQL中添加一个警告提示。这里有一个关于如何处理注入问题的链接
更新了SP,通过减少搜索模式大小和处理参数内的单引号来处理问题。当您的问题涉及错误时,最好将您看到的错误消息包含在问题中。由于在不知道错误消息的情况下很难进行调试,请尝试以下方法来缩小问题的范围 在尝试数据绑定GridView之前,请尝试重新构造代码以捕获任何可能的错误: 此外,您的存储过程可以编写得更干净一些:
ALTER PROCEDURE [dbo].[cazacliente2] (
@vbusca nvarchar(60)
, @bo int
)
AS
SELECT idcliente
, nome
, endere
, tel
, pedido
FROM Vw_Conscliente
WHERE CASE
WHEN @bo = 1 THEN nome
WHEN @bo = 2 THEN endere
WHEN @bo = 3 THEN tel
WHEN @bo = 4 THEN pedido
END LIKE @vbusca
我认为这是迄今为止最好的解决方案,没有SQL注入,在传递无效@bo时会处理,默认为nome
ALTER PROCEDURE [dbo].[cazacliente2] (@vbusca nvarchar(60), @bo int)
AS
SELECT
idcliente
, nome
, endere
, tel
, pedido
FROM
Vw_Conscliente
WHERE
CASE
WHEN @bo = 1 THEN nome
WHEN @bo = 2 THEN endere
WHEN @bo = 3 THEN tel
WHEN @bo = 4 THEN pedido
ELSE nome
END LIKE @vbusca;
它会抛出什么错误?考虑到您只是在存储过程不返回任何数据的情况下得到一个错误,请在此特定条件下测试您的代码;它通过使用动态SQL来减少冗余。单元测试使用一个新的方法来测试正在中断的情况。这保证了PROC可以处理您的数据。然后调试C程序。如果您想查看@statement字符串,请在过程中使用PRINT。这是一个很好的例子,说明了为什么SqlInjection多年来一直是OWASP风险的头号您应该避免使用由用户输入生成的部分生成动态sql。除此之外,它确实有效:如果它是C语言中一个固定的下拉列表,那么如何获得SQL注入?另一方面,如果它是一个组合框,我会更改代码。我已经像狡猾的DBA所说的那样重新编写了该过程,并且无法找到返回的存储过程“从Vw_Conscliente选择idcliente、nome、endere、tel、pedido,其中nome像%ALEJANDRO%”。请尝试使用“EXEC sp_executesql@statement”。我没有为代码创建测试环境。我非常喜欢pete的解决方案,因为您不必担心SQL注入。但是,我要添加一个else子句。将5传递给代码时会发生什么?
ALTER PROCEDURE [dbo].[cazacliente2] (@vbusca nvarchar(60), @bo int)
AS
SELECT
idcliente
, nome
, endere
, tel
, pedido
FROM
Vw_Conscliente
WHERE
CASE
WHEN @bo = 1 THEN nome
WHEN @bo = 2 THEN endere
WHEN @bo = 3 THEN tel
WHEN @bo = 4 THEN pedido
ELSE nome
END LIKE @vbusca;