sql注入是被谈的很多的一个话题,有很多的方法能够实现sql的防注入,在这里就简单说一下如果使用HttpModule来实现sql的防注入。
在项目中添加一个类让其实现IHttpModule接口。IHttpModule接口有两个方法 Init 和 Dispose。然后在Init方法中来订阅
AcquireRequestState事件。
Code ;zPh0Ml&rb$KH"H(M0 public void Dispose()ITPUB个人空间4t[5~C)Wza3^0~ { 2mz$k9x#E*R0 ITPUB个人空间 y*vGOz+} }
public void Init(HttpApplication context) h|+c]u/WF2I(m0 {ITPUB个人空间.`z#w {&E"V context.AcquireRequestState += new EventHandler(context_AcquireRequestState); p$q)m zX)DG^2g#y0 } 7@,R1[sN/H? ~0
为什么是AcquireRequestState 事件而不是Begin_Request呢 ,因为在Begin_Request执行的时候还没有加载session状态,而在处理的时侯
可能会用到session。
在AcquireRequestState 事件中我们就要进行相应的处理了,思路如下,一般网站提交数据只有两个地方,表单和url,所以就在该事件中将从这两处提交的数据截取,判断是否有一些危险字符,然后做相应处理。代码如下
Code { a/Go~&O0private void context_AcquireRequestState(object sender, EventArgs e)ITPUB个人空间;q!Y#of] i0E {ITPUB个人空间i2]'\8C s t HttpContext context = ((HttpApplication)sender).Context;
tryITPUB个人空间6JC g9Y4e6e TQ { aF:O3rK)F_0 string getkeys = string.Empty;ITPUB个人空间/aO%y4xwK#_ string sqlErrorPage = "~/Error.aspx";//转向的错误提示页面 Sx\(@:A0 string keyvalue = string.Empty;
string requestUrl = context.Request.Path.ToString(); W/o/l9c$e/X0 //url提交数据ITPUB个人空间 g:X$L)w iM:T%y if (context.Request.QueryString != null) &n4eohe-p(i0 {ITPUB个人空间+UAb/V M v for (int i = 0; i < context.Request.QueryString.Count; i++)ITPUB个人空间0|U'J\.yCy { O D7RA.TZJ0 getkeys = context.Request.QueryString.Keys[i];ITPUB个人空间7SBs[L keyvalue = context.Server.UrlDecode(context.Request.QueryString[getkeys]);
if (!ProcessSqlStr(keyvalue))ITPUB个人空间F:L"Sv7\a { G(D6w'}V%b0 context.Response.Redirect(sqlErrorPage); -Uh1c(Obp gC?e0 context.Response.End(); 'g Rx2aa0 break;ITPUB个人空间)R&^,er|!\U cLi }ITPUB个人空间 l;n7B,B?p*o:L P ^"K } J T3T_VX N R0 } },gL$t3zu0 //表单提交数据 /?]r)j0P+O0 if (context.Request.Form. != null)ITPUB个人空间`%C[qyN { ~2[,jt5r];?(v0 for (int i = 0; i < context.Request.Form.Count; i++)ITPUB个人空间LHzK U5~ {ITPUB个人空间t \+XwpP(l6F getkeys = context.Request.Form.Keys[i]; ped8P#V#?_(rN0 keyvalue = context.Server.HtmlDecode(context.Request.Form[i]); \8RG.A1C0AX0 if (getkeys == "__VIEWSTATE") continue; If!B%H/QE0 if (!ProcessSqlStr(keyvalue))ITPUB个人空间9dZez,}7t { MB7wV ~;YE0 context.Response.Redirect(sqlErrorPage);ITPUB个人空间0oW?m'oI L context.Response.End(); 2P:g:H5qK_ KF0 break;ITPUB个人空间?u"S;ExrJ5kUcX/V } KwGHqeD;o S0 } 1Y#a+r)g fk0 }ITPUB个人空间@V zzTk4g } 9l0[ K0S5F0 catch (Exception ex)ITPUB个人空间w }4Y NP%k@6p Ch { H"O?R aL"P0^0 }ITPUB个人空间]_R W/KN } -|8i p6EC0
上面的代码只是做了简单的处理,当然也可以在事件中将输入非法关键字的用户ip ,操作页面的url,时间等信息记录在数据库中或是记录在日志中。而且还用到了一个叫ProcessSqlStr的方法,这个方法就是用来处理字符串的,判断是否合法,如下
CodeITPUB个人空间/j1{{ vwCo private bool ProcessSqlStr(string str)ITPUB个人空间f_,e z,]:qx { eY)V/gE-s+K!n?G0 bool returnValue = true; C+nlGn0 tryITPUB个人空间J"BN H8[ pj { b"oo5X$p?^L/i&TZ0 if (str.Trim() != "") %Jx)@^+j w)FI A0 {ITPUB个人空间y$^~3Rt //一般将关键词组配置在webconfig中 CRu y}j;LO0 //string sqlStr = ConfigurationManager.AppSettings["FilterSql"].Trim(); G e {@8k F` kF4n0 string sqlStr = "declare |exec|varchar |cursor |begin |open |drop |creat |select |truncate";
string[] sqlStrs = sqlStr.Split('|'); ;P H _7p(t5g { x6B0 foreach (string ss in sqlStrs) (Fk,q\{'f:~4t0 {ITPUB个人空间7\/h'I}u2_db if (str.ToLower().IndexOf(ss) >= 0)ITPUB个人空间k;\h6G2u~ {ITPUB个人空间HG(F]6G m_sqlstr = ss; j,||I9vr []*Q0 returnValue = false; 5`@X2Z6SV2e.P;YP0 break; P([u(q)gj"M l0 } I3va7B7g6u0 }ITPUB个人空间DrQ!UH4Pf$V)vn }ITPUB个人空间}-kC*j&H1e\j3Z}N } "QcH$O{'R^0 catchITPUB个人空间&b4i%\"K ~3Fm {ITPUB个人空间]Xk)qz4I8n-\,y returnValue = false;ITPUB个人空间-x3n%b|Ao vo }ITPUB个人空间m"h nz#N6qzX return returnValue;ITPUB个人空间&l9I,na-t Vh-o } RCS,N5|a_0
到这儿类就写好了,再在web.config中做相应的配置就大功告成
CodeITPUB个人空间'G(? q s"}x\"p^ <httpModules>ITPUB个人空间A @+{ IQ.Q&_a'E <add type="SqlHttpModule " name="SqlHttpModule"/>ITPUB个人空间!q-B([ ?)XoF </httpModules> c0R;Uhr V6I0
用这种方法很方便,只需在这一处做处理,全站都能应用到,不过如果一个用户想用varchar 等sql的关键字来做用户名注册的话也会被挡掉,
不过应该没有人这么无聊吧,呵呵!
asp.net 防SQL注入
|