现在有很多的网站,在用户注册的时候,都会提示不要输入什么特殊符号等,因为我们用户注册的信息最终都会保存到数据库中,所有有时候对一些sql关键字要进行限制。如果我们不进行限制,被有恶意的人注意到打话,那么就可能对我们的网站产生威胁。我写的这个小程序,就是一个简单的防SQL注入的方法。
首先需要明白SQL注入是什么。简单的说SQL注入就是利用SQL关键字对网站进行恶意攻击。怎么样防,我们就还要对我们asp.net处理Http请求的过程作一个了解,首先我们的程序得到一个请求的时候,第一个会经过Http运行时,即编译过程,在这里我们的请求会被转化为机器懂的语言。下一个,我们的请求经过不同的HttpModule,即我们的Http模块。事实上,我们的请求到达模块时系统没有对这个请求做任何的处理,也就是说此时对于请求来讲,模块是一个请求的“必经之路”。我们的模块可以在这个Http请求到达真正的处理中心(HttpHandler)之前,针对这个Http请求做一些额外的工作,或者在某些情况下干脆终止满足一些条件的Http请求,从而起到一个过滤器的作用。在经过我们的模块之后,我们的Http请求才到达真正的处理中心(HttpHandler)。Http请求在经过处理之后,原路返回,经过模块,经过运行时,返回到客户端。
那么既然我们的请求无论如何都会经过HttpModule,那么我们的一些判断(如是否有SQL关键字等)能否在此进行呢?答案当然是肯定的!基本概念我们都清楚了,下面就来看看代码吧!
具体做法是:我们建立一个类继承自IHttpModule,既然继承自接口,当然就要实现接口中的方法。在IHttpModule中需要实现两个方法,一个是dispose方法,一个是Init方法。我们只要实现后者就可以了。
在Init方法中,我们需要定义一个委托,委托调用实现我们具体的过滤关键字的方法。
public void Init(HttpApplication context)
{
//在此方法中调用一个委托
//context_AcquireRequestState为委托的方法
context.BeginRequest += new EventHandler(context_AcquireRequestState);
}
/// <summary>
/// 委托中的方法
/// </summary>
/// <param ></param>
/// <returns></returns>
private void context_AcquireRequestState(object sender, EventArgs e)
{
//一定要将sender对象的Context转化为HttpContext的对象
//其中包含请求的基本对象,如request,response等
HttpContext context = ((HttpApplication)sender).Context;
//错误处理的页面,里面可以是一个温馨提示
string errorPage = "~/Error.aspx";
string keys = ""; //保存传参过来的键值
string values = ""; //保存传参过来的值
//我们的请求可以是多种形式的,如表单提交,url传值等
//我们就要对各种情况分类处理
//如果是url传参传过来的情况
if (context.Request.QueryString != null)
{
for (int i = 0; i < context.Request.QueryString.Count; i++ )
{
//得到键值
keys = context.Request.QueryString.Keys[i];
//得到值
values = context.Server.UrlDecode(context.Request.QueryString[keys]);
//如果有非法字符串,则跳转到错误提示页面
if (!this.ProcessSqlStr(values))
{
context.Response.Redirect(errorPage);
context.Response.End();
break;
}
}
}
//如果是表单提交过来打值
if(context.Request.Form != null)
{
for (int i = 0; i < context.Request.Form.Count; i++ )
{
keys = context.Request.Form.Keys[i];
values = context.Server.HtmlDecode(context.Request.Form[i]);
if (keys == "__VIEWSTATE") continue;
//如果有非法字符串,则跳转到错误提示页面
if (!this.ProcessSqlStr(values))
{
context.Response.Redirect(errorPage);
context.Response.End();
break;
}
}
}
}
/// <summary>
/// 截取字符串的方法
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private bool ProcessSqlStr(string str)
{
bool returnValue = true;
try
{
if (str.Trim() != "")
{
//非法字符串,可以写在配置文件中,易于修改
string sqlStr = "declare|exec|varchar|cursor|begin|open|drop|creat|select|truncate|int|view|procudure|insert|alter";
//将字符串用|分割为数组
string[] sqlStrs = sqlStr.Split('|');
foreach (string ss in sqlStrs)
{
//判断字符串中是否有上述字符数组中的项
if (str.ToLower().IndexOf(ss) >= 0)
{
//如果有非法字符,返回false
returnValue = false;
break;
}
}
}
}
catch
{
returnValue = false;
}
return returnValue;
}
在我们的代码实现完之后,一定不要忘了在web.config文件中,写下这样的配置信息
在<system.web>节点下的
<httpModules>
<add name="名字(可随意定义)" type="类名"/>(可以写多个add,指定不同的处理类型)
</httpModules>
注意:如果你建立的是一个web应用程序的话,那么type="命名空间.类名.程序集名称"