在中间层指定一个漏洞抽象的字段名称?
我觉得为每个字段创建一个单独的函数太麻烦了,即使它是代码生成的。
public bool Assortment_IsValueExistingOnOtherRecord(
Dictionary<string, object> exceptPkColumns,
string field, object value
)
{
var c = Connect();
var dt = new DataTable();
string sanitizedField = field.Replace("'","");
var daAssortment = new SqlDataAdapter(
string.Format(
@"SELECT 1 FROM assortment
WHERE
/* do I violate any good programming practice here? */ [{0}] = @value
AND NOT (assortment_id = @assortment_id)", field), c);
daAssortment.SelectCommand.Parameters.Add("assortment_id", exceptPkColumns["assortment_id"]);
daAssortment.SelectCommand.Parameters.Add("value", value);
daAssortment.Fill(dt);
return dt.Rows.Count == 1;
}
答案 0 :(得分:1)
[{0}] = @value
只要采取适当的措施,这是好的。 “消毒”不属于这些措施之中。
选项1:你是否对该领域的提供者有一种隐含的信任,这样你才知道他们永远不会惹你生气?例如,如果您(作为此模块的作者)是该字段的提供者,您可以相信自己。
选项2:你能创建一个将请求的字段映射到字符串的枚举/查找吗?然后,此代码的“客户端”只能请求枚举中的内容,并且您(此模块的作者)通过将其请求的枚举值映射到已知字符串而成为字段提供者。
选项3:如果字段随时间变化并且您不想使用枚举锁定,是否可以将字符串值发送到数据库进行确认?
SELECT name
FROM syscolumns
WHERE name = @name
这会将提供的名称映射到来自数据库的已知字符串,并且必须是安全的。
答案 1 :(得分:1)
从封装的角度来看,你所写的内容并没有错。
然而,正如“大卫B”提到的那样(他对此有点担心),你需要注意一些安全问题。
您生成的动态SQL受到称为“SQL注入攻击”的影响。例如,想象一下,field的值是以下字符串:
assortment_id] = 0 and assortment_id = 1
delete from assortment
select 1 from assortment where [assortment_id
这将导致数据库执行3个查询:
显然,这可能会导致一些问题。
如果通过以下方式指定“field”的值:
然后,您需要在运行任何查询之前验证数据以确保它是有效的字段值。否则你很容易受到攻击。
答案 2 :(得分:0)
使用表达式,您将拥有编译时(和Sql运行时)的安全性:
public bool Assortment_IsValueExistingOnOtherRecord<TValue>(
Dictionary<string, object> exceptPks,
Expression<Func<Assortment, TValue>> expression,
TValue value
)
propExp = expression.Body as MemberExpression;
if (propExp == null) throw new ArgumentException();
string field = propExp.Member.Name;
/* blah, blah */
}
/* Calling code */
bool exists = Assortment_IsValueExistingOnOtherRecord(
exceptPKs,
(a => a.Property1),
"property1Value"
);
使用通用TValue,您还可以获得与属性匹配的强类型值 - 避免RDBMS偶尔为您做的脑死亡。
你可以拥有整个equals表达式,甚至可以添加对&lt;的支持。和&gt; - 但是,你只是在发明LINQ到本土的ORM。 ;)
顺便说一下,exceptPK似乎有点奇怪......但也许它在上下文中有意义?
答案 3 :(得分:0)
是。所有的抽象都泄漏了。
现在,就安全性而言,如果您没有明确地信任所有呼叫者不要愚蠢(或寻求主动攻击您),您最好拥有所有可能字段的emum并根据该列表验证传入参数。