在.NET环境下为网站增加IP过滤功能
引:原文地址不记得了,这是从我的Window live spances 搬家到这里来备份
此文张用到了 .net httpModel 、URL 、xml等知识点,尤其是作者从开发设计到完成代码实现的文章流水般描述,跟上一个从需求设计到测试完整程序开发模型的缩影,读后很是觉得感觉通畅。
摘要:华能集团下某发电厂的企业网站(基于Asp.Net2.0实现,不允许修改源程序)要求实现“厂内用户可直接访问整个站点的所有页面,厂外用户只能访问指定的页面”的功能,本文将按照需求分析、方案设计、编码实现、部署应用的顺序逐步阐述整个解决方案的形成过程。
1. 需求分析
通过深入的交流和沟通,确认了该发电厂在企业网站用户访问控制方面的改进要求,大致情况如下:
a) 网站基于Asp.Net2.0实现,不允许修改源程序
b) 厂内用户可直接访问整个站点的所有页面,员工不需要身份验证
c) 厂外用户只能访问指定的页面
显而易见,他们就是针对企业网站增加一项IP过滤功能,在厂外用户访问某些敏感页面时将其拒之门外。首先我们需要设置一个IP列表和一个Url列 表,前者包含所有厂内IP,后者包含厂外用户可访问的全部Url,并且这两个列表都是可维护的;另外一个核心问题是,我们需要选择一个合理的方式将开发好 的功能模块集成到企业网站中,HttpModules义不容辞。
在Asp.Net时代,IIS 接收到请求并将其调度给 aspnet_isapi.dll之后,ASP.NET 引擎开始逐个对已配置的HTTP模块(HttpModules)进行初始化,然后再调用正确的HTTP处理程序并呈现被请求的资源,最后将所生成的标记返 回给 IIS 和请求客户端(如下图所示)。
如果你想了解更多关于HttpModules的资料,请自行查阅。
2. 方案设计
2.1. 开发环境
编程语言:C#2.0
开发工具:Visual Studio.NET2008
操作系统:windows2003 R2
2.2. 概要设计
使用HttpModules实现IP过滤功能的核心思想是:自定义一个HttpModule捕获每一个用户请求,然后获取相关的用户IP和被请求的Url进行逻辑判断,将未授权的请求重定向到一个错误提示页。Http请求授权与否的判断逻辑为:
1) 判断请求是否来自本地计算机,是则自动忽略,否则继续;
2) 判断用户IP是否属于内网(IP列表),是则忽略,否则继续;
3) 判断被请求Url是否授权所有用户访问,是则忽略,否则继续;
4) 将请求重定向到错误提示页。
在HttpApplication的BeginRequest事件中附加自定义的处理程序即可完成Http请求的捕获。此外,为了便于维护我们应将 程序运行需要的各项参数(IP列表、Url列表、错误提示页路径等等)存储于特定的XML配置文件中,为了提高效率,我们还需要将配置文件执行内存级的缓 存处理并对IP、Url匹配算法进行适当的优化。
2.3. 配置缓存算法
配置文件的缓存参照微软CommonServer项目中的实现逻辑,将配置信息持久化为实体类存储于 HttpContext.Current.Cache中,配置文件发生后缓存信息将自动清空,下次访问时再次执行持久化操作,不需重启站点。本文对 CommonServer的缓存逻辑不做深入探讨,感兴趣者可自行搜索相关资料。
2.4. IP列表算法
通过上文可知,当前项目用到的IP列表包含的数据量非常有限,就是电厂web服务器可有效识别的内网IP的穷举。
因而我们将整个IP列表缓存,使用时直接检索当前用户IP是否存在于列表之中即可。在具体IP的存储方面,我们可将其视作256进制,将IP字符串 转换为数字格式(例如:192.168.10.3可视作 192*256*256*256+168*256*256+10*256+3=3232238083,不考虑IPV6);在参数配置的格式方面,我们应同 时支持单个IP或IP段的方式增删IP列表。
2.5. Url列表算法
就具体需求而言,Url列表是一个授权外网用户访问的白名单,换个说法,“对外网用户而言除了在列表之中的其他都不可访问”,一旦数据的安全级别降 低,会不会出现“对外网用户而言除了列表之中的其他都可以访问”的情况出现呢?为了兼容这种后续场景,我们需要为Url列表定义一个“是否黑名单” (IsBlacklist)的附加参数;另外,对于动态网站穷举Url显然是不现实的,不管是维护黑名单还是白名单,所以我们可以转变一下思路,更改最终 Url为正则表达式,即:维护一个可匹配目标Url的正则表达式列表,针对用户请求的具体Url逐个正则表达式执行匹配操作,只要有一个匹配成功则认为当 前Url存在于Url列表之中。
3. 编码实现
由于本文提供全部的c#源码下载,所以本节仅对源码压缩包中的主要文件进行简要说明:
│ DotCommonWebsiteFilter.cfg.xml
│ WebsiteFilterConfiguration.cs
│ WebsiteFilterHttpModule.cs
├─Util
│ GlobesCache.cs
│ XmlAttributeReader.cs
└─WebsiteFilter
IPMatchEngine.cs
UrlMatchCondition.cs
UrlMatchEngine.cs
- DotCommonWebsiteFilter.cfg.xml
运行参数配置文件 - WebsiteFilterConfiguration.cs
配置文件实体类 - WebsiteFilterHttpModule.cs
实现了System.Web.IHttpModule接口的自定义Http模块 - GlobesCache.cs
全局缓存操控类 - XmlAttributeReader.cs
xml节点属性读取器 - IPMatchEngine.cs
IP匹配引擎 - UrlMatchCondition.cs
Url匹配条件(与正则表达式匹配) - UrlMatchEngine.cs
Url匹配引擎
WebsiteFilterHttpModule.cs中BeginRequest自定义处理程序的核心代码如下:
void context_BeginRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Request.IsLocal)//忽略本地计算机请求
return;
string ip = HttpContext.Current.Request.UserHostAddress;
if (!WebsiteFilterConfiguration.GetConfig().PickedIPs.IsMatch(ip))
{ //若在IP列表中找不到访客ip
string rawUrl = HttpContext.Current.Request.RawUrl;
UrlMatchEngine pu = WebsiteFilterConfiguration.GetConfig().PickedUrls;
//列表包含当前url且列表为黑名单、列表不包含当前url且列表不为黑名单 时需转向
//换而言之,“配备结果”与“是否黑名单”取值一致时需转向
if (pu.IsMatch(rawUrl) == pu.IsBlacklist)
{ //非公开url自动重定向
HttpContext.Current.Response.Redirect(pu.ErrorPage);
}
}
}
4. 部署应用
4.1. DotCommonWebsiteFilter.cfg.xml配置文件
配置文件的根节点为DotCommon,所有配置信息均为WebsiteFilter节点的子项。PickedUrl节点对应Url列 表,IsBlacklist(1是0否)指示是否为黑名单,ErrorPage指定错误提示页路径,其子节点add可重复出现,通过pattern属性指 定正则表达式文本,上图所示配置表示仅网站首页(default.aspx)允许外网用户访问。
PickedIP节点对应IP列表,有效子节点包括add、remove、clear三项。以上图为例,第一个add指示内网ip为 192.168.10.1、192.168.10.2、192.168.10.3、192.168.10.4、192.168.10.5五个;到第二行删 除掉192.168.10.2、192.168.10.3、192.168.10.4还剩192.168.10.1、192.168.10.5两个;到第 三行再添加上192.168.10.3,最终的内网IP列表为192.168.10.1、192.168.10.3、192.168.10.5三个。
4.2. 在企业网站中集成
- 配置好DotCommonWebsiteFilter.cfg.xml中的各项参数并拷贝到网站根目录。
- 拷贝DotCommon.WebsiteFilter.dll文件到网站bin目录。
- 在网站根目录下建立与配置文件中相对应的错误提示页(例如sorry.htm)。
- 修改Web.config在<httpModules>节点下注册WebsiteFilter模块,代码如下:
<httpModules>
<add name="WebsiteFilter"
type="DotCommon.WebsiteFilterHttpModule, DotCommon.WebsiteFilter"/>
</httpModules> - 分别从内网、外网访问企业网站查看运行效果。
结束语
本文仅针对具体需求阐述解决方案的构思过程,希望对读者能有所帮助,欢迎提出改进意见。
源码下载地址(2009-6-29):https://files.cnblogs.com/cncxz/DotCommon_WebsiteFilter.rar 或 http://u.115.com/file/f580fa83b8