此前本想在網上找找實作Asp.Net的IP位址屏蔽功能的文章來參考,但是一搜尋“IP 屏蔽 asp.net”,出現的全都是:
這篇文章寫的是程式設計部分,并沒有程式設計實作屏蔽功能,搜尋引擎上翻了幾頁也沒找到個正經寫這方面的文章,無奈隻好自己來研究實作,并寫下此文的續篇了,倒是沒什麼難度。
本文将介紹通過實作IHttpModule接口,進行判斷和屏蔽IP位址的方法。
首先,建立一個類,名為IPFilter,繼承自IHttpModule接口:
實作IHttpModule接口,并為context對象的AcquireRequestState事件添加事件處理:
事件處理方法:
這裡的主要功能是從Session中讀取使用者IP,再從緩存中讀取IP位址屏蔽清單,周遊IP位址屏蔽資料,判斷是否應當屏蔽目前IP,如果判斷為屏蔽,就關閉輸出,讓用戶端無法通路。
黃色高亮區域:這裡是在判斷Session是否為空,其原因是不能保證執行到這裡時Session總是存在的,我曾在有異步通路的頁面中遇到過這裡報錯的情況,是以這樣處理比較穩妥。
藍色高亮區域:輔助方法,其代碼見下文:
此方法用于擷取IP位址。
此方法用于從資料庫中讀取有效的IP位址屏蔽資料,并将其裝入緩存。
緩存時間設定為固定3分鐘。
至此,過濾類就實作了。
接下來還需要向Web.Config檔案中注冊此HttpModule處理程式:
這樣就全部完成了。
屏蔽測試:
添加IP屏蔽資料後3分鐘内(依據緩存時間設定),被屏蔽的通路者繼續浏覽網站就會出現這樣的提示了。
源代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
namespace MySite
{
public class IPFilter : IHttpModule
{
void context_AcquireRequestState(object sender, EventArgs e)
{
var c = (sender as HttpApplication).Context;
if (c.Session == null) return;
IPAddress ip = null;
if (c.Session["IP"] == null)
{
c.Session["IP"] = ip = IPAddress.Parse(擷取用戶端IP位址(c));
}
else ip = c.Session["IP"] as IPAddress;
if (c.Cache["IPFilter"] == null) 更新IP屏蔽清單緩存();
var l = c.Cache["IPFilter"] as List<IP位址屏蔽>;
foreach (var f in l)
if (f.檢測是否被屏蔽(ip))
{
c.Response.Close();
break;
}
}
void 更新IP屏蔽清單緩存()
using (var c = new DatabaseEntities())
var iplist = c.IP位址屏蔽.Where(f => f.過期時間 > DateTime.Now).ToList();
HttpContext.Current.Cache.Insert("IPFilter",
iplist,
null,
DateTime.Now.AddMinutes(3),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.AboveNormal,
null);
/// <summary>
/// 獲得目前頁面用戶端的IP
/// </summary>
public static string 擷取用戶端IP位址(HttpContext c)
string result = String.Empty;
result = c.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(result))
result = c.Request.ServerVariables["REMOTE_ADDR"];
result = c.Request.UserHostAddress;
return "0.0.0.0";
return result;
#region IHttpModule 成員
public void Dispose()
public void Init(HttpApplication context)
context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
#endregion
}
}
總結來說沒什麼難度,但是因為這段代碼在每次請求中都會執行一次,是以對性能要求很高,如果你有什麼優化方面的建議,歡迎提出。
下載下傳本文的XPS版本:
<a href="http://www.uushare.com/user/icesee/file/1850426" target="_blank"></a>
本文轉自斯克迪亞部落格園部落格,原文連結:http://www.cnblogs.com/SkyD/archive/2009/07/31/1535569.html,如需轉載請自行聯系原作者