"IP地址的长度为32位,分为4段,每段8位,用十进制数字表示,每段数字范围为0~255,段与段之间用句点隔开。"
  由此我们了解到,IP地址实际上是一个32位正整数,在C#中可以使用uint类型来表示,但SQLServer数据库里好像没有对应的类型;转而使用数据库支持的int类型的话,则会出现溢出的情况;因此我们做出妥协:使用long(bigint)类型。
  TIP:
  int取值范围:-2,147,483,648 到 2,147,483,647
  uint取值范围: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()实例方法获取IP的4个段的值,然后将它们组合为一个整数,下面将提供这个扩展方法:
  ///
  /// 将IP地址转为整数形式
  ///
  /// 整数
  public static long 转换为整数(this IPAddress ip)
  {
  int x = 3;
  long o = 0;
  foreach (byte f in ip.GetAddressBytes())
  {
  o += (long)f 《 8 * x--;
  }
  return o;
  }
  你可以这样使用这个扩展方法:
  IPAddress.Parse("127.0.0.1")。转换为整数()
  这里还有一个用于逆转换的扩展方法,用于将long转回IPAddress:
  /// www.tygj123.com
  /// 将整数转为IP地址
  ///
  /// IP地址
  public static IPAddress 转换为IP地址(this long l)
  {
  var b = new byte[4];
  for (int i = 0; i < 4; i++)
  {
  b[3 - i] = (byte)(l 》 8 * i & 255);
  }
  return new 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屏蔽记录的代码:
  ///
  /// 添加一个新的IP屏蔽区段
  ///
  /// 起始IP,如61.51.200.0
  /// 终止IP,如61.51.255.255
  /// 屏蔽截止时间
  /// ID号
  public static Guid 添加(string IP区段起始值, string IP区段终止值, DateTime 过期时间)
  {
  var id = Guid.NewGuid();
  var sip = IPAddress.Parse(IP区段起始值)。转换为整数();
  var eip = IPAddress.Parse(IP区段终止值)。转换为整数();
  using (var c = new SiteMainEntities())
  {
  //检测是否已存在相同的IP屏蔽记录
  var a = c.IP地址屏蔽。Where(f => f.区段起始值 == sip && f.区段终止值 == eip);
  //如果存在则更新其过期时间
  if (a.Count()>0)
  {
  var l = a.First();
  if (l.过期时间 < 过期时间) l.过期时间 = 过期时间;
  }
  //不存在则正常添加一个新的屏蔽记录 www.qcwy123.com
  else c.AddToIP地址屏蔽(new IP地址屏蔽 { ID = id, 过期时间 = 过期时间, 区段起始值 = sip, 区段终止值 = eip });
  c.SaveChanges();
  }
  return id;
  }
  检测指定IP地址是否被屏蔽的代码:
  ///
  /// 检测指定IP地址是否已受到屏蔽
  ///
  /// 要检测的IP地址
  /// 是否属于已屏蔽的IP
  public static bool 检测是否被屏蔽(string IP地址)
  {
  var ip = IPAddress.Parse(IP地址)。转换为整数();
  using (var c = new SiteMainEntities())
  {
  return c.IP地址屏蔽。Count(f => f.过期时间 > DateTime.Now && ip >= f.区段起始值 && ip <= f.区段终止值) > 0;
  }
  }
  这种方案比起以往的字符串验证方案来说优雅了许多,并可以提高数据库查询的效率,建议各位在日后的网站开发中都采用此方案。

Asp.net的IP地址屏蔽功能设计的更多相关文章

  1. 通过IP地址屏蔽各种“推广”

    事情的起因是这样的:最近老是发现iPhone应用的底部出现各种横条广告,一开始以为是Google的广告推广,所以没管它,但是最近这些广告越来越猖狂,里面的内容越来越垃圾.今天仔细一看,原来不是Goog ...

  2. asp.net获取ip地址的方法

    在ASP中使用 Request.ServerVariables("REMOTE_ADDR") 来取得客户端的IP地址,但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的I ...

  3. Asp.Net_获取IP地址

    //方法一 HttpContext.Current.Request.UserHostAddress; //方法二 HttpContext.Current.Request.ServerVariables ...

  4. 如何在 Linux 下大量屏蔽恶意 IP 地址

    很多情况下,你可能需要在Linux下屏蔽IP地址.比如,作为一个终端用户,你可能想要免受间谍软件或者IP追踪的困扰.或者当你在运行P2P软件时.你可能想要过滤反P2P活动的网络链接.如果你是一名系统管 ...

  5. .htaccess根据IP地址限制访问

    屏蔽IP地址 屏蔽IP地址有时是非常必要的,比如对于一个外贸公司网站,来自国内的访问是不会带来任何经济效益的,而且还占用服务器资源,造成访问延迟等问题. 如果要屏蔽某一特定IP可以使用: order ...

  6. 通过ip地址获取当前地理位置

    1.  使用接口的方式: 这种方式是相对稳定,而且提供的数据相对稳定,提供接口的地方很多,大家可以参照 http://www.hujuntao.com/api/the-ip-address-api-a ...

  7. QQ IP 地址查询相关

    1.QQwry.dat格式分析和查询IP位置的PHP程序 以前的追捕数据库太大,而且很久没有更新了. 所以我想到利用QQwry.dat这个文件查询IP所在位置,QQwry.dat 在很多地方都能找到, ...

  8. 负载均衡的场景下ASP.NET Core如何获取客户端IP地址

    在ASP.NET中,使用负载均衡时,可以通过ServerVariables获取客户端的IP地址. var ip = request.ServerVariables["HTTP_X_FORWA ...

  9. ASP.NET获取真正的客户端IP地址的6种方法

    Request.ServerVariables("REMOTE_ADDR") 来取得客户端的IP地址,但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的IP地址,而不是真 ...

随机推荐

  1. 【Linux】鸟哥的Linux私房菜基础学习篇整理(三)

    1. gzip [-cdtv#] filename:压缩.参数:-c:将压缩的数据输出到屏幕上,可通过数据重定向进行处理:-d:解压缩的参数:-t:可以用来检验一个压缩文件的一致性,查看文件有无错误: ...

  2. Linux企业级开发技术(7)——libevent企业级开发之锁和线程

    编写多线程程序的时候,在多个线程中同时访问同样的数据并不总是安全的. libevent的结构体在多线程下通常有三种工作方式: 1.某些结构体内在地是单线程的:同时在多个线程中使用它们总是不安全的. 2 ...

  3. HDOJ(HDU) 2162 Add ‘em(求和)

    Problem Description Write a program to determine the summation of several sets of integers. Input Th ...

  4. HDOJ 2056 Rectangles

    Problem Description Given two rectangles and the coordinates of two points on the diagonals of each ...

  5. [LeetCode] 141&142 Linked List Cycle I & II

    Problem: Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without ...

  6. max Sum(简单动态规划)

    http://acm.hdu.edu.cn/showproblem.php?pid=1003 / 给组测试数据 1 7 2 3 -4 -5 6 7 8 一个关键问题 : 什么时候将开始位置重新赋值 即 ...

  7. SRM 406(1-250pt, 1-500pt)

    DIV1 250pt 题意:有几家宠物店,vecort<int>A表示每家宠物店含有小狗占小狗总数的百分比.现在要做扇形统计图统计每家店的小狗百分比,如下图,问作出来的扇形统计图中最多含有 ...

  8. 简单的FIRST+集演示程序

    /* * 该程序用于计算某个非终结符的 FIRST+ 集合 * RexfieldVon * 2013年6月30日16:02:47 */ #include <stdio.h> #includ ...

  9. Hard 随机选择subset @CareerCup

    算法同上题 package Hard; import CtCILibrary.AssortedMethods; /** * Write a method to randomly generate a ...

  10. [Unity3d][NGUI]两种思路解决AssetBundle的依赖关系.

    接上文. 使用上文中的AssetBundle打包方式生成的文件包括了依赖关系中的文件. 一般的使用中并不会发现什么问题. 可是当配合NGUI的时候,使用dynamicFont时打包AssetBundl ...