熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

Asp.net設計IP地址屏蔽功能教程

2013-11-13 10:13:48  來源: .NET編程 

  

  於安全考慮幾乎每個動態網站都具備IP地址屏蔽功能而網上流傳的很多關於該功能的教程大都采用字符串保存和驗證IP地址我認為這是不太科學的我試圖找到最佳的設計方案
IP地址的長度為分為每段用十進制數字表示每段數字范圍為段與段之間用句點隔開

  由此我們了解到IP地址實際上是一個位正整數在C#中可以使用uint類型來表示但SQLServer數據庫裡好像沒有對應的類型轉而使用數據庫支持的int類型的話則會出現溢出的情況因此我們做出妥協使用long(bigint)類型

  TIP:

  int取值范圍

  uint取值范圍

  long取值范圍那麼如何將IP地址轉為整數呢?我們看到IPAddress類中有一個[否決的]實例屬性Address這個屬性的確可以返回一個long值但是測試一下得到的數據確實這樣的

   >

   –>

  的確該讓它否決這樣的整數對我們來說毫無意義我們是無法通過這樣的方法比較傳入的IP是否介於兩個IP值之間的

  那麼只有自己動手了我們將通過IPAddress類的GetAddressBytes()實例方法獲取IP的個段的值然後將它們組合為一個整數下面將提供這個擴展方法


  /// <summary>

  /// 將IP地址轉為整數形式

  /// </summary>

  /// <returns>整數</returns>

  public static long 轉換為整數(this IPAddress ip)

  {

  int x = ;

  long o = ;

  foreach (byte f in ipGetAddressBytes())

  {

  o += (long)f << * x;

  }

  return o;

  }

  你可以這樣使用這個擴展方法


  IPAddressParse()轉換為整數()

  這裡還有一個用於逆轉換的擴

  展方法用於將long轉回IPAddress


  /// <summary>

  /// 將整數轉為IP地址

  /// </summary>

  /// <returns>IP地址</returns>

  public static IPAddress 轉換為IP地址(this long l)

  {

  var b = new byte[];

  for (int i = ; i < ; i++)

  {

  b[ i] = (byte)(l >> * i & );

  }

  return new IPAddress(b);

  }

  這樣我們就可以通過計算得到正確並有意義的整數了

   >

   –>

  OK確立了方案核心下面開始設計SQLServer數據表

  

  這樣設計後在添加時將起始和終止IP地址轉為long類型並存入並指定一個過期時間

  在驗證時只需要獲取所有未過期的條目比較傳入的IP地址是否介於起始值和終止值之間即可

  以往通過字符串存儲和驗證的方案中屏蔽時要麼屏蔽一個精確的IP地址要麼就屏蔽一段或兩段IP**要想屏蔽之間的IP的話將會非常麻煩

  而我們這樣設計就可以輕松實現在數據庫裡存儲的是在數據庫中是即使使用肉眼也能極快地判斷傳入的地址是否介於它們之間更不要說計算機查詢了

  下面為數據表生成EDM模型

  

  添加IP屏蔽記錄的代碼


  /// <summary>

  /// 添加一個新的IP屏蔽區段

  /// </summary>

  /// <param name=IP區段起始值>起始IP</param>

  /// <param name=IP區段終止值>終止IP</param>

  /// <param name=過期時間>屏蔽截止時間</param>

  /// <returns>ID號</returns>

  public static Guid 添加(string IP區段起始值 string IP區段終止值 DateTime 過期時間)

  {

  var id = GuidNewGuid();

  var sip = IPAddressParse(IP區段起始值)轉換為整數();

  var eip = IPAddressParse(IP區段終止值)轉換為整數();

  using (var c = new SiteMainEntities())

  {

  //檢測是否已存在相同的IP屏蔽記錄

  var a = cIP地址屏蔽Where(f => f區段起始值 == sip && f區段終止值 == eip);

  //如果存在則更新其過期時間

  if (aCount()>)

  {

  var l = aFirst();

  if (l過期時間 < 過期時間) l過期時間 = 過期時間;

  }

  //不存在則正常添加一個新的屏蔽記錄

  else cAddToIP地址屏蔽(new IP地址屏蔽 { ID = id 過期時間 = 過期時間 區段起始值 = sip 區段終止值 = eip });

  cSaveChanges();

  }

  return id;

  }

  檢測指定IP地址是否

  被屏蔽的代碼


  /// <summary>

  /// 檢測指定IP地址是否已受到屏蔽

  /// </summary>

  /// <param name=IP地址>要檢測的IP地址</param>

  /// <returns>是否屬於已屏蔽的IP</returns>

  public static bool 檢測是否被屏蔽(string IP地址)

  {

  var ip = IPAddressParse(IP地址)轉換為整數();

  using (var c = new SiteMainEntities())

  {

  return cIP地址屏蔽Count(f => f過期時間 > DateTimeNow && ip >= f區段起始值 && ip <= f區段終止值) > ;

  }

  }

  這種方案比起以往的字符串驗證方案來說優雅了許多並可以提高數據庫查詢的效率建議各位在日後的網站開發中都采用此方案


From:http://tw.wingwit.com/Article/program/net/201311/12978.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.