好吧我承认这是一种罪恶,就是在生生地剥夺别人浏览网页的权利.
很多时候我们要封人的IP,其实主要是为了保护自己的安全.
如果有自己的主机当然用IIS的IP限定更好了,只是对于广大的穷虚拟机用户来说..恩..
很多论坛啊什么的都有IP过滤,没有仔细去统计过,也没有参考过.进行IP过滤最好的是在IIS的请求处理中直接过滤,其次是在ISAPI层,等到沦落到要在ASP.net中处理的时候,效率多少有点惨不忍睹,可是又有什么办法呢.要是这个处理过程还要在System.Web.UI.Page中处理,那么…….请允许我默默走过一回……….
好吧,我们来实现一个IP过滤系统,思路和我的那个URL回写的差不多.
先来考察过滤方案,这里假定使用一个最简单的字符串匹配方法,即从一个IP的起始开始匹配,如果成功就被认作是加入了黑名单,直接拦截.例如设置一个拦截规则是
60.162.23.
那么所有客户端IP是60.162.23.开头的IP将会被批量拒绝.
那如果有例外呢?我们就需要把这个例外的IP在拦截之前提前放行.
好的,先就用这个吧,开工.
首先考虑到灵活性,我们假定在web.config中允许用户自定义要封锁或例外的IP.
那么我们先来创建一个配置类.在ASP.net中,实现自动从web.config中取出SectionGroup的方法是使用 System.Configuration.IConfigurationSectionHandler 接口,这个接口只有一个方法,就是 Create(),用来返回一个格式化的自定义对象.
函数原型如下:
Public Function Create(ByVal parent As Object, ByVal configContext As Object, ByVal section As System.Xml.XmlNode) As Object
其中的section就是表示配置节所在区段的XML节点树了.
我们最终实现的类如下,具体定义请参考注释:
NamespaceFS.HttpServer
'在这个处理过程中使用的是自定义的配置类,配置类包含了要封锁的IP列表
'以及IP被阻止时候提示的信息.为了友好,我们给这个提示信息定义一个变量,
'代表当前客户端的地址,"$ip$",允许自定义,但是可以用默认值.
PublicClassIpFilterConfigClass
PubliclistAsSystem.Collections.Generic.List(OfString)
PublicmesAsString
PublicSubNew()
mes="您当前的IP: $ip$ 不在允许的访问列表中,系统拒绝您的访问."
list=NewSystem.Collections.Generic.List(OfString)
EndSub
EndClass
'创建配置对象的类
PublicClassIpFilterConfig
ImplementsSystem.Configuration.IConfigurationSectionHandler'实现接口
'下面这个是接口的唯一方法,用于创建自定义的对象
PublicFunctionCreate(ByValparentAsObject,ByValconfigContextAsObject,ByValsectionAsSystem.Xml.XmlNode)AsObjectImplementsSystem.Configuration.IConfigurationSectionHandler.Create
DimlAsIpFilterConfigClass=NewIpFilterConfigClass
DimnAsSystem.Xml.XmlNode
ForEachnInsection.ChildNodes'遍历整个区域的所有子节点
Ifn.Name="add"Then'如果节点名是add,那么就把这个节点的文本加到IP的黑名单中
l.list.Add(n.InnerText)
ElseIfn.Name="message"Then'如果节点名是message,那么就改写IP封锁的时候提示信息
l.mes=n.InnerText
Else'除此以外的话,一律当作黑名单中的例外.为了识别,在前面加上"-"号
l.list.Add("-"&n.InnerText)
EndIf
Next
Returnl
EndFunction
EndClass
EndNamespace
OK………..下面我们来创建HttpMoudle,具体的请参考注释.代码如下:
NamespaceFS.HttpServer
PublicClassIpFilter
ImplementsIHttpModule'实现IHttpModule
PublicSubDispose()ImplementsSystem.Web.IHttpModule.Dispose
EndSub
'这是接口的初始化过程,我们在这里使用AddHandler方法来捕捉请求的BeginRequest方法.
'效率应该比较高了吧..我觉得 :-(
PublicSubInit(ByValcontextAsSystem.Web.HttpApplication)ImplementsSystem.Web.IHttpModule.Init
AddHandlercontext.BeginRequest,AddressOfIpFilter
EndSub
'这个过程是执行IP过滤的主方法的.
PublicSubIpFilter(ByValsenderAsObject,ByValeAsEventArgs)
DimlAsIpFilterConfigClass
DimconAsHttpApplication=CType(sender,HttpApplication)
'首先从缓存中提取配置,如果缓存中没有,那么就通过配置节来创建,然后加入高速缓存中
l=con.Context.Cache.Item("$FantasyStudio.IpFilter_"&con.Request.ApplicationPath)
IflIsNothingThen
l=System.Web.Configuration.WebConfigurationManager.GetWebApplicationSection("FantasyStudio.IpFilter")
con.Context.Cache.Add("$FantasyStudio.IpFilter_"&con.Request.ApplicationPath,l,Nothing,System.Web.Caching.Cache.NoAbsoluteExpiration,System.Web.Caching.Cache.NoSlidingExpiration,System.Web.Caching.CacheItemPriority.Normal,Nothing)
EndIf
DimsAsString
DimcheckAsString=con.Request.UserHostAddress
'遍历每条记录,如果都不匹配则放行
ForEachsInl.list
Ifs.StartsWith("-")Then
'如果匹配行是使用"-"开头的,那么提前退出循环达到白名单的目的,防止被封杀
Ifcheck.IndexOf(s.Remove(0,1))=0Then
ExitSub
EndIf
Else
'但是如果不幸IP匹配了..那么...就报错吧..然后中止服务...:-(
Ifcheck.IndexOf(s)=0Then
con.Response.StatusCode=503
con.Response.Write(l.mes.Replace("$ip$",check))
con.Response.End()
ExitSub
EndIf
EndIf
Next
EndSub
EndClass
EndNamespace
OK….建工程,编译,然后放到网站的bin目录中.现在打开web.config文件,加入配置节.
1.在<configSections>中加入配置段说明:
<sectionname="FantasyStudio.IpFilter"type="FS.HttpServer.IpFilterConfig"/>
2.在</configSections>后加入回写规则的配置段.如下:
<FantasyStudio.IpFilter>
<!--
IP Config
<add></add>
-->
<message><![CDATA[对不起,您当前的访问IP $ip$ 在空间的禁止访问列表中,或不在允许访问的列表中,请和系统管理员联系.]]></message>
</FantasyStudio.IpFilter>
3.哦,上面的<add>里面如果什么都不写,那是会封掉所有访问IP的,注意修改..现在加入HttpMoudle,在<system.web>下的<httpModules>节点中加入钩子:
<addname="FS.HttpServer.IpFilter"type="FS.HttpServer.IpFilter"/>
4.恩…应该完工了,现在保存配置,然后..刷新浏览器.祝你好运,别把自己封掉了.. 🙂
—————-
编译好的DLL可以在这里下载: http://www.ttpretty.com/Download/Detail.aspx?cguid=37300d99-41cf-65af-f29b-83ebcf06bd39&guid=69925f24-976f-2dfb-6a90-bd2968225de0
配置..自行配置吧,一样的.