我的插件有OleDbCommand,我试图实现以避免SQL注入。在此之前,我使用简单的字符串进行查询,但我不喜欢这样。现在我用于插入记录的代码如下所示:
try
{
OleDbConnection rConn = new OleDbConnection(args[3]);
rConn.Open();
using (OleDbCommand insert = new OleDbCommand(String.Format(Globals.QUERY_INSERT_CLICK, args[4]), rConn))
{
insert.Parameters.Add("id", OleDbType.BigInt, 20);
insert.Parameters.Add("email", OleDbType.VarChar, 255);
insert.Parameters.Add("clickTime", OleDbType.Date, 20);
insert.Parameters.Add("subscriberId", OleDbType.BigInt, 20);
insert.Parameters.Add("link", OleDbType.VarChar, 255);
insert.Parameters.Add("sendQueueId", OleDbType.BigInt, 20);
insert.Parameters.Add("mailingListName", OleDbType.VarChar, 255);
insert.Parameters.Add("newsletterId", OleDbType.BigInt, 20);
insert.Parameters.Add("sendDate", OleDbType.Date, 20);
insert.Parameters[0].Value = clickitem.Id;
insert.Parameters[1].Value = clickitem.Email;
insert.Parameters[2].Value = clickitem.ClickTime;
insert.Parameters[3].Value = clickitem.SubscriberId;
insert.Parameters[4].Value = clickitem.Link;
insert.Parameters[5].Value = clickitem.SendQueueId;
insert.Parameters[6].Value = mailingListName;
insert.Parameters[7].Value = newsletterID;
insert.Parameters[8].Value = sendDate;
insert.Prepare();
insert.ExecuteNonQuery();
}
rConn.Close();
}
catch (OleDbException oldbex)
{
logger.WriteToLog("GETCLICKS", "OleDbException: " + Globals.ERROR_INSERT_CLICK + oldbex.Message);
}
catch (Exception ex)
{
logger.WriteToLog("GETCLICKS", Globals.ERROR_INSERT_CLICK + ex.Message);
}
我有成千上万的插件,我在日志中看到其中一些没有正确插入。例外情况告诉我,例如不能从bigint转换为datetime和类似的东西。虽然我的大多数记录都已正确插入,但我想知道哪些插入查询确实导致了错误。我怎么能弄明白呢?
N.B。在使用此方法之前,我可以访问我的查询字符串,并立即发现错误。现在我想我对SQL注入的免疫力会给自己造成一些混乱
答案 0 :(得分:1)
由于您提到接收不同/多个数据转换错误,我的建议是在捕获OleDbException时改进日志记录。
您可以在初始“GETCLICKS”日志条目之后立即将每个参数值写入日志。这样可以让您更好地了解来自用户的错误格式。
答案 1 :(得分:1)
标准SQL错误不会显示导致错误的列或值。
最简单的方法是将SQL语句和参数值添加到日志记录调用中。
string params = string.Join(Environment.NewLine,
insert.Parameters
.Select(p => string.Format("{0} : {1}",
p.Name,
p.Value))
.ToArray()
);
string message = string.Format("{0}: {1}{2}\n{3}\n{4}",
"OleDbException: " ,
Globals.ERROR_INSERT_CLICK,
oldbex.Message,
insert.CommandText,
params);
logger.WriteToLog("GETCLICKS", message );
答案 2 :(得分:0)
参数Value属性是Object泛型类型。所以它接受你分配给它的任何东西。当然,这不是处理数据的好方法。我将尝试将值转换为参数的相应数据类型,并避免将伪值发送到数据库。这样,您将立即在参数分配中捕获错误,而不是在执行插入
时例如:
insert.Parameters[2].Value = Convert.ToDateTime(clickitem.ClickTime);
如果这不是一个有效的日期时间,它将在Convert.ToDateTime失败,你会注意到你的日志
答案 3 :(得分:-1)
创建一个构造函数,它将oledbcomndand作为输入参数,您可以尝试通过循环参数集合来记录OldedbComamnd.CommandText。如下面的示例所示,SQLcommand(与OLedbCommand或多或少相同)
或Easy Way - 抛出异常时,在日志中写入OLDEBCommand.ComamndText。
下面是我为SQL命令的StoredProcExecutionException创建的示例。你可以完全复制这个OleDbCommand。希望这有帮助
public StoredProcExecutionException(string message, Exception innerException ,SqlCommand sqlCommand)
: base(Convert.ToString(sqlCommand.CommandType ,CultureInfo.InvariantCulture)+" : "
+ Convert.ToString(sqlCommand.CommandText, CultureInfo.InvariantCulture)
+ "Failed. " + Convert.ToString(message, CultureInfo.InvariantCulture), innerException)
{
StringBuilder sb = new StringBuilder();
foreach (SqlParameter param in sqlCommand.Parameters)
{
if (sb.Length > 0) sb.Append(",");
sb.AppendFormat("{0}='{1}'", param.ParameterName, Convert.ToString(param.Value, CultureInfo.InvariantCulture));
}
StringBuilder sbHeader = new StringBuilder();
sbHeader.AppendLine(String.Format(CultureInfo.InvariantCulture,"{0} :{1} Failed. {2}", sqlCommand.CommandType, sqlCommand.CommandText, message));
sbHeader.AppendFormat("Exec {0} ", sqlCommand.CommandText);
sbHeader.Append(sb.ToString());
}