新人第一帖

ASP999999 2010-08-10 05:22:03
1.为什么要用SqlParameter?
2.使用参数除了能防止注入式攻击,还有别的好处么?网上搜索说着是标准写法?
3.谁给个标准写法看看。我需要使用参数对数据库进行增删改的操作。
4.是不是一定要用SqlDataAdatper才能增删改?只修改一条,这样会不会有点慢?
...全文
231 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
michael_ls 2010-08-12
  • 打赏
  • 举报
回复
滚回去学ado.net
ASP999999 2010-08-10
  • 打赏
  • 举报
回复
6楼朋友。非常感谢。下次用UBB标注一下就更容易阅读了。先回家了。一会看。谢谢。
老Key 2010-08-10
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 jiuchunyoung 的回复:]
C# code

因为通过SQL语句的方式,有时候存在脚本注入的危险,所以在大多数情况下不建议用拼接SQL语句字符串方式,希望通过SqlParameter实现来实现对数据的操作,针对SqlParameter的方式我们同样可以将其封装成一个可以复用的数据访问类,只是比SQL语句的方式多了一个SqlParameter的参数。

具体代码如下:

1. //<summary>

2……
[/Quote]娃娃写的不错啊。。呵呵呵。。细心,切有爱心的人不多 了。。。
ZHENNIUBILE 2010-08-10
  • 打赏
  • 举报
回复
顶你,和我水平并不多。 我会努力超过你的。
ibatis 2010-08-10
  • 打赏
  • 举报
回复
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using DataAccessHelper.BaseHelper;
using System.Configuration;
using Utility;
using System.Web;
using System.Web.Caching;

namespace DataAccessHelper
{
/// <summary>
/// Summary description for SqlServerHepler.
/// </summary>
public class SqlServerHepler
{
private static readonly string connectionString = ConfigurationSettings.AppSettings["ConnectionString"];


#region ExecuteNonQuery

/// <summary>
/// sql文本执行
/// </summary>
/// <param name="commandText"></param>
/// <returns></returns>
public static int ExecuteNonQuerySql(string commandText)
{
return SqlHelper.ExecuteNonQuery(connectionString, CommandType.Text,commandText);
}

public static int ExecuteNonQuerySql(string commandText, params SqlParameter[] commandParameters)
{
return SqlHelper.ExecuteNonQuery(connectionString, CommandType.Text, commandText, commandParameters);
}

public static int ExecuteNonQuery(string commandText,CommandType commandType , ICollection commandParameters)
{
return SqlHelper.ExecuteNonQuery(connectionString, commandType, commandText, commandParameters);
}


/// <summary>
/// 过程执行
/// </summary>
/// <param name="spName"></param>
/// <param name="commandParameters"></param>
/// <returns></returns>
public static int ExecuteNonQueryProcedure(string spName, ICollection commandParameters)
{
return SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName, commandParameters);
}

public static int ExecuteNonQueryProcedure(string spName, params SqlParameter[] commandParameters)
{
return SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName, commandParameters);
}

/// <summary>
/// 加事物的执行
/// </summary>
/// <param name="transaction"></param>
/// <param name="commandType"></param>
/// <param name="commandText"></param>
/// <returns></returns>
public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText)
{
return SqlHelper.ExecuteNonQuery(transaction,commandType,commandText);
}

public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
return SqlHelper.ExecuteNonQuery(transaction,commandType,commandText,commandParameters);
}

public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText, ICollection commandParameters)
{
return SqlHelper.ExecuteNonQuery(transaction, commandType, commandText, commandParameters);
}

public static int ExecuteNonQuery(SqlTransaction transaction, string spName, params object[] parameterValues)
{
return SqlHelper.ExecuteNonQuery(transaction,spName,parameterValues);

}

#endregion

#region ExecuteScalar

public static object ExecuteScalar(string commandText)
{
return SqlHelper.ExecuteScalar(connectionString, CommandType.Text, commandText);
}

public static object ExecuteScalar(string commandText,CommandType comandType,ICollection commandParameters)
{
return SqlHelper.ExecuteScalar(connectionString, CommandType.Text, commandText, commandParameters);
}

public static string ExecuteScalar(string commandText,string defaultStr)
{
object objValue = SqlHelper.ExecuteScalar(connectionString, CommandType.Text, commandText);
if(objValue==null)
{
return defaultStr;
}
else
{
return objValue.ToString();
}
}

public static int ExecuteScalar(string commandText,int defaultInt)
{
string strValue=ExecuteScalar(commandText,defaultInt.ToString());
try
{
return Int32.Parse(strValue);
}
catch
{
return defaultInt;
}
}

public static decimal ExecuteScalar(string commandText,decimal defaultDecimal)
{
string strValue=ExecuteScalar(commandText,defaultDecimal.ToString());
try
{
return Decimal.Parse(strValue);
}
catch
{
return defaultDecimal;
}
}

#endregion

#region ExecuteDataset

public static DataSet ExecuteDatasetSql(string commandText)
{
return SqlHelper.ExecuteDataset(connectionString, CommandType.Text, commandText);
}

public static DataSet ExecuteDatasetSql(string commandText, params SqlParameter[] commandParameters)
{
return SqlHelper.ExecuteDataset(connectionString, CommandType.Text, commandText, commandParameters);
}

public static DataSet ExecuteDatasetProcedure(string spName, params SqlParameter[] commandParameters)
{
return SqlHelper.ExecuteDataset(connectionString, CommandType.StoredProcedure, spName, commandParameters);
}

public static DataSet ExecuteDataset(string spName,CommandType commandType, params SqlParameter[] commandParameters)
{
return SqlHelper.ExecuteDataset(connectionString, commandType, spName, commandParameters);
}

public static DataSet ExecuteDataset(string spName, ICollection commandParameters)
{
return SqlHelper.ExecuteDataset(connectionString, CommandType.StoredProcedure, spName, commandParameters);
}

public static DataSet ExecuteDataset(string commandText,CommandType commandType, ICollection commandParameters)
{
return SqlHelper.ExecuteDataset(connectionString, commandType, commandText, commandParameters);
}

#endregion

#region ExecuteReader

public static SqlDataReader ExecuteReader(string commandText)
{
return SqlHelper.ExecuteReader(connectionString, CommandType.Text, commandText);
}

public static SqlDataReader ExecuteReader(string spName,params SqlParameter[] commandParameters)
{
return SqlHelper.ExecuteReader(connectionString, CommandType.StoredProcedure, spName, commandParameters);
}

public static SqlDataReader ExecuteReader(string spName,CommandType commandType,params SqlParameter[] commandParameters)
{
return SqlHelper.ExecuteReader(connectionString, commandType, spName, commandParameters);
}

#endregion


/// <summary>
/// 用事务执行Sql语句
/// </summary>
/// <param name="sql1"></param>
/// <param name="sql2"></param>
/// <returns></returns>
public static bool ExexuteNonQueryByTrans(string[] sql)
{
using (SqlConnection sqlcon = new SqlConnection(connectionString))
{
sqlcon.Open();
SqlTransaction trans;
trans = sqlcon.BeginTransaction();

SqlCommand sqlcom = new SqlCommand();

sqlcom.Connection = sqlcon;
sqlcom.CommandType = CommandType.Text;
sqlcom.Transaction = trans;
try
{
for (int i = 0; i < sql.Length; i++)
{
if (sql[i].Length > 0 && sql[i] != "")
{
sqlcom.CommandText = sql[i];
sqlcom.ExecuteNonQuery();
}
}

trans.Commit();
return true;
}
catch (Exception)
{
trans.Rollback();
throw;


}

}
}

}
}
ASP999999 2010-08-10
  • 打赏
  • 举报
回复
知道了。@后面是参数名。
参数名和字段是对应的么?
ajq1989 2010-08-10
  • 打赏
  • 举报
回复
好贴!!!!
ASP999999 2010-08-10
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 linda_liuyu 的回复:]
SqlParameter提供参数的.
如果你写的是存储过程
例如修改
sqlParameter[] parms=new SqlParameter[]{
new sqlparameter("@username",'ly')
new sqlparameter("@password",'123456')
new sqlparameter("@UserID",'1')

};
……
[/Quote]

这里的@是什么意思,字段名么?为什么要前面写个@?
Peter200694013 2010-08-10
  • 打赏
  • 举报
回复
找本看看吧

推荐
C#与.Net3.5高级程序设计
ASP999999 2010-08-10
  • 打赏
  • 举报
回复
1~5楼以及类似的忠告没意义的回复作为范例,大家不要模仿了,没意义回复。
感谢6楼的例子。看来我编译器问题,总出问题,刚Command没点出Parameters的属性。现在有了。挂一会,新人,分少,如果就此问题还有延伸问题继续跟点贴,外延过多我重新开贴。莫急。谢谢。
Love_Air523824 2010-08-10
  • 打赏
  • 举报
回复
ExecuteNonQuery()是执行删除,更新的,返回 int
ExecuteReader()是读的
等等还有好多。自己好好研究一下吧
JiuchunYoung 2010-08-10
  • 打赏
  • 举报
回复
第一种:
squery=lcase(Request.ServerVariables("QUERY_STRING"))
sURL=lcase(Request.ServerVariables("HTTP_HOST"))

SQL_injdata =":|;|>|<|--|sp_|xp_|\|dir|cmd|^|(|)|+|$|'|copy|format|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare"

SQL_inj = split(SQL_Injdata,"|")

For SQL_Data=0 To Ubound(SQL_inj)
if instr(squery&sURL,Sql_Inj(Sql_DATA))>0 Then
Response.Write "SQL通用防注入系统"
Response.end
end if
next



第二种:
SQL_injdata =":|;|>|<|--|sp_|xp_|\|dir|cmd|^|(|)|+|$|'|copy|format|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare"

SQL_inj = split(SQL_Injdata,"|")

If Request.QueryString<>"" Then
For Each SQL_Get In Request.QueryString
For SQL_Data=0 To Ubound(SQL_inj)
if instr(Request.QueryString(SQL_Get),Sql_Inj(Sql_DATA))>0 Then
Response.Write "SQL通用防注入系统"
Response.end
end if
next
Next
End If

If Request.Form<>"" Then
For Each Sql_Post In Request.Form
For SQL_Data=0 To Ubound(SQL_inj)
if instr(Request.Form(Sql_Post),Sql_Inj(Sql_DATA))>0 Then
Response.Write "SQL通用防注入系统"
Response.end
end if
next
next
end if

第三种
<%
'--------定义部份------------------
Dim Str_Post,Str_Get,Str_In,Str_Inf,Str_Xh,Str_db,Str_dbstr
'自定义需要过滤的字串,用 "■"分离
Str_In = "'■;■and■exec■insert■select■delete■update■count■*■%■chr■mid■master■truncate■char■declare"
'----------------------------------
%>

<%
Str_Inf = split(Str_In,"■")
'--------POST部份------------------
If Request.Form<>"" Then
For Each Str_Post In Request.Form

For Str_Xh=0 To Ubound(Str_Inf)
If Instr(LCase(Request.Form(Str_Post)),Str_Inf(Str_Xh))<>0 Then
'--------写入数据库----------头-----
Str_dbstr="DBQ="+server.mappath("SqlIn.mdb")+";DefaultDir=;DRIVER={Microsoft Access Driver (*.mdb)};"
Set Str_db=Server.CreateObject("ADODB.CONNECTION")
Str_db.open Str_dbstr
Str_db.Execute("insert into SqlIn(Sqlin_IP,SqlIn_Web,SqlIn_FS,SqlIn_CS,SqlIn_SJ) values('"&Request.ServerVariables("REMOTE_ADDR")&"','"&Request.ServerVariables("URL")&"','POST','"&Str_Post&"','"&replace(Request.Form(Str_Post),"'","''")&"')")
Str_db.close
Set Str_db = Nothing
'--------写入数据库----------尾-----
Response.Write "<Script Language=JavaScript>alert('请不要在参数中包含非法字符尝试注入!');</Script>"
Response.Write "非法操作!系统做了如下记录:<br>"
Response.Write "操作IP:"&Request.ServerVariables("REMOTE_ADDR")&"<br>"
Response.Write "操作时间:"&Now&"<br>"
Response.Write "操作页面:"&Request.ServerVariables("URL")&"<br>"
Response.Write "提交方式:POST<br>"
Response.Write "提交参数:"&Str_Post&"<br>"
Response.Write "提交数据:"&Request.Form(Str_Post)
Response.End
End If
Next

Next
End If
'----------------------------------

'--------GET部份-------------------
If Request.QueryString<>"" Then
For Each Str_Get In Request.QueryString

For Str_Xh=0 To Ubound(Str_Inf)
If Instr(LCase(Request.QueryString(Str_Get)),Str_Inf(Str_Xh))<>0 Then
'--------写入数据库----------头-----
Str_dbstr="DBQ="+server.mappath("SqlIn.mdb")+";DefaultDir=;DRIVER={Microsoft Access Driver (*.mdb)};"
Set Str_db=Server.CreateObject("ADODB.CONNECTION")
Str_db.open Str_dbstr
Str_db.Execute("insert into SqlIn(Sqlin_IP,SqlIn_Web,SqlIn_FS,SqlIn_CS,SqlIn_SJ) values('"&Request.ServerVariables("REMOTE_ADDR")&"','"&Request.ServerVariables("URL")&"','GET','"&Str_Get&"','"&replace(Request.QueryString(Str_Get),"'","''")&"')")
Str_db.close
Set Str_db = Nothing
'--------写入数据库----------尾-----

Response.Write "<Script Language=JavaScript>alert('请不要在参数中包含非法字符尝试注入!);</Script>"
Response.Write "非法操作!系统做了如下记录:<br>"
Response.Write "操作IP:"&Request.ServerVariables("REMOTE_ADDR")&"<br>"
Response.Write "操作时间:"&Now&"<br>"
Response.Write "操作页面:"&Request.ServerVariables("URL")&"<br>"
Response.Write "提交方式:GET<br>"
Response.Write "提交参数:"&Str_Get&"<br>"
Response.Write "提交数据:"&Request.QueryString(Str_Get)
Response.End
End If
Next
Next
End If
%>
第3中方法需要你自己建个数据库表
linda_liuyu 2010-08-10
  • 打赏
  • 举报
回复
SqlParameter提供参数的.
如果你写的是存储过程
例如修改
sqlParameter[] parms=new SqlParameter[]{
new sqlparameter("@username",'ly')
new sqlparameter("@password",'123456')
new sqlparameter("@UserID",'1')

};
JiuchunYoung 2010-08-10
  • 打赏
  • 举报
回复

因为通过SQL语句的方式,有时候存在脚本注入的危险,所以在大多数情况下不建议用拼接SQL语句字符串方式,希望通过SqlParameter实现来实现对数据的操作,针对SqlParameter的方式我们同样可以将其封装成一个可以复用的数据访问类,只是比SQL语句的方式多了一个SqlParameter的参数。

具体代码如下:

1. //<summary>

2. //执行SQL语句,返回影响的记录数

3. //</summary>

4. //<returns>影响的记录数</returns>

5. public static int ExecuteSql(string StrSql, params SqlParameter[] cmdParms)

6. {

7. using (SqlConnection connection = new SqlConnection(conString))

8. {

9. using (SqlCommand cmd = new SqlCommand())

10. {

11. PrepareCommand(cmd, connection, null, StrSql, cmdParms);

12. int rows = cmd.ExecuteNonQuery();

13. cmd.Parameters.Clear();

14. return rows;

15. }

16. }

17.}

18.//<summary>

19.//执行查询语句,返回DataSet

20.//</summary>

21.//<returns>DataSet</returns>

22.public static DataSet Query(string StrSql, params SqlParameter[] cmdParms)

23.{

24. using (SqlConnection connection = new SqlConnection(conString))

25. {

26. SqlCommand cmd = new SqlCommand();

27. PrepareCommand(cmd, connection, null, StrSql, cmdParms);

28. using (SqlDataAdapter da = new SqlDataAdapter(cmd))

29. {

30. DataSet ds = new DataSet();

31. da.Fill(ds, "ds");

32. cmd.Parameters.Clear();

33. return ds;

34. }

35. }

36.}
sqlparameter的使用

2009-4-30





//写法一

2

3 string SelectSQL = "select * from customers where customerid=@customerid";

4 SqlCmd.Connection = SqlConn;

5 SqlCmd.CommandText = SelectSQL;

6 SqlCmd.Parameters.Add("@customerid", SqlDbType.NVarChar, 50).Value = "alfki".ToUpper();

7

8 //写法二

9

10

11 SqlParameter myParameter = new SqlParameter("@userID",SqlDbType.Nvarchar,50")

12 (userID);

13 SqlCmd.parameters.Add(myParameter);

14

//方法3

public int InsertCalendar(int uKey,DateTime cTime,int cTimes,int cFreq,string cTitle,string cContent)

{

int Num = 0;

SqlParameter[] parameters =

{

new SqlParameter("uKey",SqlDbType.Int),

new SqlParameter("cTime",SqlDbType.DateTime),

new SqlParameter("cTimes",SqlDbType.Int),

new SqlParameter("cFreq",SqlDbType.Int),

new SqlParameter("cTitle",SqlDbType.VarChar),

new SqlParameter("cContent",SqlDbType.VarChar)

};

parameters[0].Value = uKey;

parameters[1].Value = cTime;

parameters[2].Value = cTimes;

parameters[3].Value = cFreq;

parameters[4].Value = cTitle;

parameters[5].Value = cContent;

//调用数据操作类DataOper(自己写的)

//"Insert_Calender"是存储过程名称,parameters是传给存储过程的数据集

Num = DataOper.RunParaMeters_Int("Insert_Calender", parameters);

return Num;

}









注入攻击都是来自于客户端,无论是表单提交、URL传值还是Cookie等,其实原理都是一样的。到了服务器端可以分成三种情况:数字、日期时间、字符串。

  一、数字。

  如何注入?

  假设我们要实现一个显示新闻的页面,我们可能会随手写下下面的代码:

  stringid=Request.QueryString["id"];

  stringsql="select*fromnewswhereColID="+id;

  如果传递过来的id是我们想像的数字(比如168),那么自然不会有什么问题。但是如果传递过来的id是“168deletefromtable”的话,那么sql的值就变成了“select*fromtablewhereColID=168deletefromnews”。对于SQLServer来说是支持一次提交多条SQL语句的,这个为我们提供了方便之余也为SQL注入敞开了大门。显然如果这条SQL语句被执行的话,那么news表里的记录就都没有了。

  那么如何预防呢?很简单,因为ColID字段的类型是int的,那么我们只需要验证一下传递过来的id是不是整数就可以了。是整数就不存在注入;如果不是那么就有可能存在注入。即使不存在注入,把一个不是整数的id拼接进去也会造成执行错误。

  所以说不管是不是为了预防SQL注入,也都应该验证id是不是整数。

  验证方法嘛,可以用TryParse,可以用正则,也可以自己写函数验证。但是不建议用try异常的方式,因为这个有效率问题。

  这里还有一个特殊情况,就是对于批量删除这类的会传递过来多个数字,比如“1,2,3,10”,这个也需要验证一下,万一有人利用这个漏洞呢。至于验证方法也很简单,自己写个函数就ok了。

  二、日期时间

  这个和数字的情况是一样的,验证是不是日期时间即可。

  三、字符串

  最麻烦、争议最大的就是这个了。

  先看一下如何注入

  比如我们先要按照新闻标题来进行查询,可能写的代码:

  stringkey=txtTitle.Text;

  stringsql="select*fromnewswheretitlelike'%"+key+"%'";

  这个又是如何注入的呢?我想先问大家一个问题:如果key的值永远都不会包含单引号,那么会不会被注入进来?

  那么用了单引号又是如何注入的呢?假设key="'deletefromnews--",那么sql的值就是“select*fromnewswheretitlelike'%'deletefromnews--'”。

  先用一个单引号和前面的单引号组成一对封闭的单引号,这一对单引号内部('%')就作为字符串处理,而外面的就被作为SQL语句处理,而第二个单引号被“--”给注释掉了,这样就保证了整个sql语句的正确性。

  这是注入的一种方法。

  那么如何来防止呢?想想刚才的问题,如果没有单引号是不是就天下太平了呢?对于这种情况(前面的“数字”的情况不算),到目前为止我是没发现不用单引号,还能够注入进来的方法。也许是我孤陋寡闻吧,不知道各位高手是否知道对于这种情况,不用单引号还能注入进来的方法。

  既然找到了罪魁祸首,那么就好办了,把单引号干掉就ok了。key=key.Replace("'","''");这时候sql的值就是”select*fromnewswheretitlelike'%''deletefromnews--'”。

  对于SQL来说在一对单引号内部的两个单引号表示一个字符串形式的单引号。这样我们就把罪魁祸首改造成了字符串了。在一对单引号内的“--”也是普通的字符串而不代表注释。

  罪魁祸首是单引号,想不明白为什么有许多人都去过滤“delete、update”这一类的关键字,他们都是安善良民呀,他们是很冤枉的。当然了,如果前提是程序都已经写好了,不能修改内部代码,那就另当别论了。至于“--”顶多算是帮凶,如果您不放心的话,把他处理了也行。

  总结:数字、日期时间的,验证类型;字符串的,处理好单引号。

  另外为了安全起见,不要用sa连接数据库,xp_cmdshell这一类的有危险的扩展存储过程也应该处理一下(比如删除)。

  ps:添加修改数据的时候可以用参数化的SQL语句,但是目的不是防止注入,而是重用执行计划。

  还有就是js脚本的问题,这个还没有仔细考虑,可以用html编码的方式,也可以用替换的方式,还有ubb的漏洞等。


guohelv0519 2010-08-10
  • 打赏
  • 举报
回复
建议楼主还是先花些时间系统的学一遍 ADO.NET。
祈祷 2010-08-10
  • 打赏
  • 举报
回复
不错,看看了哦!
xinv19shi 2010-08-10
  • 打赏
  • 举报
回复
SqlDataAdatper 是用来查的
Only_You_forver 2010-08-10
  • 打赏
  • 举报
回复
果然是新人,
路漫漫其修远啊。。。。
  • 打赏
  • 举报
回复
ADO。NET啊!
下班了走人

110,561

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧