天天看點

通過HttpModule實作IP位址屏蔽功能

此前本想在網上找找實作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,如需轉載請自行聯系原作者