"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. Nodejs爬虫进阶教程之异步并发控制

    Nodejs爬虫进阶教程之异步并发控制 之前写了个现在看来很不完美的小爬虫,很多地方没有处理好,比如说在知乎点开一个问题的时候,它的所有回答并不是全部加载好了的,当你拉到回答的尾部时,点击加载更多,回 ...

  2. STL中的Traits编程技法

    最近在看读<STL源码剖析>,看到Traits编程技法这节时,不禁感慨STL源码作者的创新能力.那么什么是Traits编程技法呢?且听我娓娓道来: 我们知道容器的许多操作都是通过迭代器展开 ...

  3. POJ 2762 Going from u to v or from v to u?(强联通 + TopSort)

    题目大意: 为了锻炼自己的儿子 Jiajia 和Wind 把自己的儿子带入到一个洞穴内,洞穴有n个房间,洞穴的道路是单向的. 每一次Wind 选择两个房间  x 和 y,   让他的儿子从一个房间走到 ...

  4. 【转】java中float与byte[]的互转 -- 不错

    原文网址:http://tjmljw.iteye.com/blog/1767716 起因:想把一个float[]转换成内存数据,查了一下,下面两个方法可以将float转成byte[]. 方法一 imp ...

  5. sublime text3安装SublimeREPL--解决不能运行input()的问题

    原文地址:http://blog.chinaunix.net/uid-12014716-id-4269991.html 一.安装包管理器(如果已经安装可以忽略) 1.简单的安装方法:使用Ctrl+`快 ...

  6. 使用Array

    public class UsingArray {     public static void output(int[]Array)     {         if(Array!=null)    ...

  7. docs

    https://www.eucalyptus.com/docs/eucalyptus/3.4/index.html  [Eucalyptus PDF官方下载] http://aws.amazon.co ...

  8. Clairewd’s message - HDU 4300(next[]运用)

    题目大意:给两个串第一个串是翻译表(密文可以通过翻译表翻译成明文),第二个串是由密文+明文组成,前面是密文(完整的),后面是明文(未必完整),问能不能把第二个串补全,输出最短的一种可能.   分析:题 ...

  9. Java同步工具类总结

    先谈谈闭锁和栅栏的区别: 1.关键区别在于,所有线程必须同时到达栅栏位置,才能继续执行. 2.闭锁用于等待某一个事件的发生,举例:CountDownLatch中await方法等待计数器为零时,所有事件 ...

  10. 《Java 并发编程实战》读书笔记之二:图文讲述同步的另一个重要功能:内存可见性

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17288243 加锁(synchronized同步)的功能不仅仅局限于互斥行为,同时还存在另 ...