在我们的数据库访问层中,我们有一些动态查询创建。例如,我们有以下方法来构建ORDER BY
子句的一部分:
protected string BuildSortString(string sortColumn, string sortDirection, string defaultColumn)
{
if (String.IsNullOrEmpty(sortColumn))
{
return defaultColumn;
}
return String.Format("{0} {1}", sortColumn, sortDirection);
}
问题是,sortColumn
和sortDirection
都来自外部作为字符串,所以当然应该采取措施防止可能的注入攻击。有没有人知道如何做到这一点?
答案 0 :(得分:11)
如果您 来处理字符串,那么白名单是最好的选择。首先,sortDirection
应该对白名单非常简单:与"asc"
/ "desc"
不区分大小写,您应该设置。对于其他人,我倾向于将已知列列入白名单,可能是通过传递预期的Type
来获取数据并进行验证。但是在绝对压力下,你可以用正则表达式来限制(比方说)强制执行它们都是严格字母数字(在az,AZ,0-9范围内 - 如果需要可能是下划线) - 然后添加[]
,即
return string.Format("[{0}] {1}", sortColumn, sortDirection);
但是:严格的已知列的白名单会更好,就像方向的枚举一样。
答案 1 :(得分:1)
另一种解决方案,如果您可以更改方法以接受int
而不是string
参数。
protected string BuildSortString(int sortColumn, int sortDirection, string defaultColumn)
{
if (String.IsNullOrEmpty(sortColumn))
{
return defaultColumn;
}
//sortdirection 0-> "ASC" else "DESC"
//sorColumn 1 for your firstcolumn, 2 for your second column etc.
return String.Format("{0} {1}", sortColumn, sortDirection==0? " ASC " : " DESC ");
}
祝你好运。
答案 2 :(得分:0)
您可以使用大型CASE语句执行此操作,您可以根据传递的列名称和方向进行切换。 There's an SO answer on that here。你将会看到如下代码:
SELECT
*
FROM
My_Table
WHERE
Whatever = @something
ORDER BY
CASE @sort_order
WHEN 'ASC' THEN
CASE @order_by
WHEN 'surname' THEN surname
WHEN 'forename' THEN forename
WHEN 'fullname' THEN fullname
ELSE surname
END
ELSE '1'
END ASC,
CASE @sort_order
WHEN 'DESC' THEN
CASE @order_by
WHEN 'surname' THEN surname
WHEN 'forename' THEN forename
WHEN 'fullname' THEN fullname
ELSE surname
END
ELSE '1'
END DESC
答案 3 :(得分:0)
解决方案:cmd.Parameters或EscapedString,但我更喜欢cmd.Parameters(总是工作,你喜欢预期的例外)
示例:
cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID IN (?, ?)";
cmd.Parameters.Add("?ID1", OdbcType.VarChar, 250).Value = email1;
cmd.Parameters.Add("?ID2", OdbcType.VarChar, 250).Value = email2;
使用带参数的预准备语句有助于防御SQL 在大多数常见情况下进行注射,否则会进行插值 将不受信任的内容转换为字符串,然后将该字符串作为SQL执行 声明。
但是查询参数取代了单个值。你不能使用 查询参数作为动态表名称列的替代 name,值列表(例如,对于IN()谓词),表达式或SQL 关键字。
对于这些情况,您可以使用过滤或白名单等技术 因此,不要将不受信任的内容插入到SQL字符串中。
过滤是您删除任何可能导致的字符的地方 麻烦。如果您知道您的动态列名称应该只是 字母数字字符,然后在您的变量之前应用过滤器 在SQL中使用它。或者,如果变量与a不匹配,则拒绝变量 正则表达式,如/ ^ [A-Za-z0-9] * $ /
答案 4 :(得分:0)
你可以这样做:
public string BuildSortString(string sortColumn, SortDirection direction, string defaultColumn)
{
string sortDirection = direction.ToString();
if (String.IsNullOrEmpty(sortColumn))
{
return VerifyColumn(defaultColumn);
}
return String.Format("{0} {1}", VerifyColumn(sortColumn), sortDirection);
}
private string VerifyColumn(string column)
{
switch (column) // fill this with a whitelist of accepted columns
{
case "some_column":
return column;
}
return String.Empty; // the column must be invalid (do whatever you want here)
}
public enum SortDirection
{
ASC, DESC
}