在做机房收费系统的时候,曾经利用过传递参数的形式来将值传递给SQL语句或者存储过程,因为这样可以通过参数化的查询来帮助抵御“SQL 注入”式攻击,这种攻击者会将命令插入SQL语句,从而危机服务器的安全。
SqlParameter Param = new SqlParameter("@CourseID", 4);
这样可以从一定程度上来抵御SQL注入,但做的还不是很好,细心的话,你会发现SqlParameter这个类有7个构造函数,每个构造函数的参数都不同。既然要通过传参数给SQL语句赋值,那么为了做到匹配度最高,我们也可以把数据库存储的数据类型和大小也相应的匹配,这样做还可以提高查询执行性能,因为他们可帮助数据库服务器将传入命令与适当的缓存计划进行准确匹配。
SqlParameter Params = new SqlParameter("@CourseID", SqlDbType.VarChar, 50, "CourseID");
注释:上述采用了SqlParameter构造函数的形式,第一个参数传递的是注入的参数,第二是是类型,第三个参数是大小,第四个参数是数据库中相对应的列的名称。
改进
使用ParameterDirection(指定查询内的有关 DataSet 的参数的类型。)枚举型类型来对上述进行改进。
其中ParameterDirection有四个成员:Input(输入参数)、OutPut(输出参数)、InOutPut(输入输出参数)、ReturnValue(操作的返回值)
传递参数过程
SqlParameter[] Params = new SqlParameter[2];
DataBase DB = new DataBase();
string strsql = "DELETE From UserAnswermr WHERE UserID= @UserID and PaperID=@PaperID";
Params[0] = DB.MakeInParam("@UserID", SqlDbType.VarChar, 50, userid); //用户ID
Params[1] = DB.MakeInParam("@PaperID", SqlDbType.Int, 4, paperid);
引入ParameterDirection
//公有方法,实例化一个用于调用存储过程的参数
//输入:
// ParamName - 参数名称
// DbType - 参数类型
// Size - 参数大小
// Direction - 传递方向
// Value - 值
public SqlParameter MakeParam(string ParamName, SqlDbType DbType, Int32 Size, ParameterDirection Direction, object Value)
{
SqlParameter Param;
if(Size > 0)
Param = new SqlParameter(ParamName, DbType, Size);
else Param = new SqlParameter(ParamName, DbType);
Param.Direction = Direction;
if (Value != null)
Param.Value = Value;
return Param;
}
//公有方法,实例化一个用于调用存储过程的输入参数
//输入:
// ParamName - 参数名称
// DbType - 参数类型
// Size - 参数大小
// Value - 值
public SqlParameter MakeInParam(string ParamName, SqlDbType DbType, int Size, object Value)
{
return MakeParam(ParamName, DbType, Size, ParameterDirection.Input, Value);
}
总结
通过引入ParameterDirection,一方面提高了查询的效率,另一方面更增加了传值得安全性。