zoukankan      html  css  js  c++  java
  • 通过HttpModule实现IP地址屏蔽功能 (转)

    此前本想在网上找找实现Asp.Net的IP地址屏蔽功能的文章来参考,但是一搜索“IP 屏蔽 asp.net”,出现的全都是:

    image

    image这些都是对我此前写的《细说Asp.net的IP地址屏蔽功能设计》一文的无情转载,不仅不保留出处、作者,而且连标题都没一个与我原文相同的~~

    这篇文章写的是程序设计部分,并没有编程实现屏蔽功能,搜索引擎上翻了几页也没找到个正经写这方面的文章,无奈只好自己来研究实现,并写下此文的续篇了,倒是没什么难度。

    本文将介绍通过实现IHttpModule接口,进行判断和屏蔽IP地址的方法。

    (HttoModule的基础知识可以参阅这里:http://www.tracefact.net/Asp-Net/Introduction-to-Http-Module.aspx

    阅读前请先参阅《细说Asp.net的IP地址屏蔽功能设计》一文,本文将使用这篇文章中提出的思路,并将使用文中创建的数据库、实体类。

    首先,新建一个类,名为IPFilter,继承自IHttpModule接口:

    image 

    实现IHttpModule接口,并为context对象的AcquireRequestState事件添加事件处理:

    image

    (因为我们要用到Session,而在早于AcquireRequestState的事件中Session还未被初始化。参考于:http://www.cnblogs.com/junqilian/archive/2008/03/07/1095454.html

    事件处理方法:

    image

    这里的主要功能是从Session中读取用户IP,再从缓存中读取IP地址屏蔽列表,遍历IP地址屏蔽数据,判断是否应当屏蔽当前IP,如果判断为屏蔽,就关闭输出,让客户端无法访问。

    黄色高亮区域:这里是在判断Session是否为空,其原因是不能保证执行到这里时Session总是存在的,我曾在有异步访问的页面中遇到过这里报错的情况,所以这样处理比较稳妥。

    绿色高亮区域:这是在《细说Asp.net的IP地址屏蔽功能设计》一文中提供的实体类方法。

    蓝色高亮区域:辅助方法,其代码见下文:

    image

    此方法用于获取IP地址。

    image

    此方法用于从数据库中读取有效的IP地址屏蔽数据,并将其装入缓存。

    缓存时间设置为固定3分钟。

    至此,过滤类就实现了。

    接下来还需要向Web.Config文件中注册此HttpModule处理程序:

    image

    这样就全部完成了。

    屏蔽测试:

    image

    添加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"];

                }

     

                if (string.IsNullOrEmpty(result))

                {

                    result = c.Request.UserHostAddress;

                }

     

                if (string.IsNullOrEmpty(result))

                {

                    return "0.0.0.0";

                }

     

                return result;

            }

     

            #region IHttpModule 成员

     

            public void Dispose()

            {

     

            }

     

            public void Init(HttpApplication context)

            {

                context.AcquireRequestState += new EventHandler(context_AcquireRequestState);

            }

     

            #endregion

        }

    }

    总结来说没什么难度,但是因为这段代码在每次请求中都会执行一次,所以对性能要求很高,如果你有什么优化方面的建议,欢迎提出。

  • 相关阅读:
    ubuntu16.04搭建jdk1.8运行环境
    window如何查看被占用端口的使用情况
    Windows下80端口被进程System占用的解决方法
    java.lang.OutOfMemoryError:PermGen space tomcat7 内存溢出
    GitLab服务器IP地址修改
    Ubuntu输入ifconfig找不到IP地址,只有lo问题
    git命令如何删除文件或文件夹
    数组转List
    Java NIO 缓冲区
    MySQL数据类型-整型
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/1535966.html
Copyright © 2011-2022 走看看