asp.net获取ip地址:Asp.net的IP地址屏蔽功能设计来源: 发布时间:星期四, 2009年2月12日 浏览:526次 评论:0
出于安全考虑几乎每个动态网站WebSite都具备IP地址屏蔽功能而网上流传很多有关该功能教程大都采用串保存和验证IP地址我认为这是不太科学我试图找到最佳设计方案 “IP地址长度为32位分为4段每段8位用十进制数字表示每段数字范围为0~255段和段的间用句点隔开” 由此我们了解到IP地址实际上是个32位正整数在C#中可以使用u类型来表示但SQLServer数据库里好像没有对应类型;转而使用数据库支持类型话则会出现溢出情况;因此我们做出妥协:使用long(big)类型 TIP: 取值范围:-2,147,483,648 到 2,147,483,647 u取值范围:0 到 4,294,967,295 long取值范围:-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 那么如何将IP地址转为整数呢?我们看到IPAddress类中有个“[否决]”例子属性Address这个属性确可以返回个long值但是测试下得到数据确实这样: “127.0.0.1” -> 16777343 “127.0.0.2” –> 33554559 确该让它“否决”这样整数对我们来说毫无意义我们是无法通过这样思路方法比较传入IP是否介于两个IP值的间 那么只有自己动手了我们将通过IPAddress类GetAddressBytes例子思路方法获取IP4个段值然后将它们组合为个整数下面将提供这个扩展思路方法: /// <summary> /// 将IP地址转为整数形式 /// </summary> /// <s>整数</s> public long 转换为整数(this IPAddress ip) { x = 3; long o = 0; foreach ( f in ip.GetAddressBytes) { o (long)f << 8 * x--; } o; } 你可以这样使用这个扩展思路方法: IPAddress.Parse("127.0.0.1").转换为整数 这里还有个用于逆转换扩展思路方法用于将long转回IPAddress: /// <summary> /// 将整数转为IP地址 /// </summary> /// <s>IP地址</s> public IPAddress 转换为IP地址(this long l) { var b = [4]; for ( i = 0; i < 4; i) { b[3 - i] = ()(l >> 8 * i & 255); } IPAddress(b); } 这样我们就可以通过计算得到正确并有意义整数了: “127.0.0.1” -> 2130706433 “127.0.0.2” –> 2130706434 OK确立了方案核心下面开始设计SQLServer数据表: 这样设计后在添加时将起始和终止IP地址转为long类型并存入并指定个过期时间 在验证时只需要获取所有未过期条目比较传入IP地址是否介于起始值和终止值的间即可 以往通过串存储和验证方案中屏蔽时要么屏蔽个精确IP地址要么就屏蔽段或两段IP如“192.168.*.*”要想屏蔽“192.168.1.200”到“192.168.4.64”的间IP话将会非常麻烦; 而我们这样设计就可以轻松实现:“192.168.1.200”在数据库里存储是“3232235976”“192.168.4.64”在数据库中是“3232236608”即使使用肉眼也能极快地判断传入地址是否介于它们的间更不要说计算机查询了 下面为数据表生成EDM模型: 添加IP屏蔽记录代码: /// <summary> /// 添加个新IP屏蔽区段 /// </summary> /// <param name="IP区段起始值">起始IP如61.51.200.0</param> /// <param name="IP区段终止值">终止IP如61.51.255.255</param> /// <param name="过期时间">屏蔽截止时间</param> /// <s>ID号</s> public Guid 添加( IP区段起始值, IP区段终止值, DateTime 过期时间) { var id = Guid.NewGuid; var sip = IPAddress.Parse(IP区段起始值).转换为整数; var eip = IPAddress.Parse(IP区段终止值).转换为整数; using (var c = SiteMainEntities) { //检测是否已存在相同IP屏蔽记录 var a = c.IP地址屏蔽.Where(f => f.区段起始值 sip && f.区段终止值 eip); //如果存在则更新其过期时间 (a.Count>0) { var l = a.First; (l.过期时间 < 过期时间) l.过期时间 = 过期时间; } //不存在则正常添加个新屏蔽记录 c.AddToIP地址屏蔽( IP地址屏蔽 { ID = id, 过期时间 = 过期时间, 区段起始值 = sip, 区段终止值 = eip }); c.SaveChanges; } id; } 检测指定IP地址是否被屏蔽代码: /// <summary> /// 检测指定IP地址是否已受到屏蔽 /// </summary> /// <param name="IP地址">要检测IP地址</param> /// <s>是否属于已屏蔽IP</s> public bool 检测是否被屏蔽( IP地址) { var ip = IPAddress.Parse(IP地址).转换为整数; using (var c = SiteMainEntities) { c.IP地址屏蔽.Count(f => f.过期时间 > DateTime.Now && ip >= f.区段起始值 && ip <= f.区段终止值) > 0; } } 这种方案比起以往串验证方案来说优雅了许多并可以提高数据库查询效率建议各位在日后网站WebSite开发中都采用此方案 0
相关文章读者评论发表评论 |