惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
D
DataBreaches.Net
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog RSS Feed
Recent Announcements
Recent Announcements
The Register - Security
The Register - Security
S
Secure Thoughts
Y
Y Combinator Blog
The Last Watchdog
The Last Watchdog
L
LINUX DO - 最新话题
V2EX - 技术
V2EX - 技术
腾讯CDC
GbyAI
GbyAI
G
Google Developers Blog
博客园 - 司徒正美
博客园 - 三生石上(FineUI控件)
T
The Exploit Database - CXSecurity.com
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
Schneier on Security
Schneier on Security
Microsoft Security Blog
Microsoft Security Blog
Jina AI
Jina AI
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
MyScale Blog
MyScale Blog
Help Net Security
Help Net Security
K
Kaspersky official blog
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
AI
AI
MongoDB | Blog
MongoDB | Blog
Scott Helme
Scott Helme
J
Java Code Geeks
Engineering at Meta
Engineering at Meta
H
Heimdal Security Blog
H
Help Net Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
云风的 BLOG
云风的 BLOG
Microsoft Azure Blog
Microsoft Azure Blog
S
Security Affairs
TaoSecurity Blog
TaoSecurity Blog
The GitHub Blog
The GitHub Blog
Hacker News: Ask HN
Hacker News: Ask HN
Martin Fowler
Martin Fowler
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Project Zero
Project Zero
T
The Blog of Author Tim Ferriss
Last Week in AI
Last Week in AI

博客园 - peace

MYSQL分页存储过程及事务处理 审批流设计方案的探究 WEB项目(B/S系统)打包安装(总结篇) 文件上传之断点续传方案 再次分享一个多选文件上传方案 SQL SERVER里的赋值机制闲聊 FLEX4.0开发流媒体视频播放器(总结篇) 告别ADO.NET实现应用系统无缝切换的烦恼(总结篇) SQL SERVER行转列应用小结 SQL SERVER函数——表值函数的处理 纠正网上流传的SQL取某一时间的当月第一天和最后一天的时间写法 SQL SERVER游标操作 告别.NET生成报表统计图的烦恼 发现联想手机P630型号的一个严重的系统Bug thinkpad T400型号安装server2003系统驱动共享 分享一个.NET版的多选文件上传操作示例 JS给页面标签添加事件(或超链接链接) 让默认焦点的按钮无虚框(又来无聊了) 利用ASP.NET日期控件制作“会议日程安排”(贴首页过把瘾)
一个简单的httpModule应用
peace · 2009-01-09 · via 博客园 - peace

     本来标题应该加上输出过滤的,想想还是不加好了,看了老赵的关于整站关键字过滤的文章,感觉还晕乎,以前也没怎么用过httpModule这东西,在网上看了下相关的文章,讲的还是比较多的,看到一篇关于输出过滤的文章,原文地址是http://www.cnblogs.com/zgqys1980/archive/2008/09/02/1281895.html 基本还算能看明白,呵呵,我这个算是转载吧。

     原文的输出过滤主要是通过ReleaseRequestState这个事件来处理的,即执行完所有请求事件处理后发生,也就是请求处理全部结束后再进行过滤,这么一来截获的是整个page的html源文件了,然后对源文件内容进行特殊字符替换过滤处理(当然在替换前可以将原内容进行相关写入操作保存起来),捕获完成是以"</html>"为标志,因为最终在浏览器中呈现的html文件内容都是以"</html>"结尾的。把输出过滤的处理类贴下面(保留原作者注释同时也加了几句注释,另外注释掉的部分代码是将替换前的原替换前的html内容保存处理)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Reflection;
using System.Text.RegularExpressions;
using System.IO;
namespace httpModuleOutputFilter
{
public class OutputFilter : IHttpModule
    {
        
private HttpApplication _contextApplication;
        
public void Init(HttpApplication context)
        {
            _contextApplication 
= context;
            
//绑定事件,在对此请求处理过程全部结束后进行过滤操作
            context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);

        }

public void Dispose()
        {
            _contextApplication 
= null;
            _contextApplication.Dispose();
        }
/**/
        
/// <summary>
        
/// 对此HTTP请求处理的过程全部结束
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>
        void context_ReleaseRequestState(object sender, EventArgs e)
        {
            HttpApplication application 
= (HttpApplication)sender;//这里需要针对ASPX页面进行拦截
            string[] temp = application.Request.CurrentExecutionFilePath.Split('.');
            
if (temp.Length > 0 && temp[temp.Length - 1].ToLower() == "aspx")
            {
                
//装配过滤器
                application.Response.Filter = new RawFilter(application.Response.Filter);//绑定过滤器事件
                
//RawFilter filter = (RawFilter)application.Response.Filter;
                
//filter.OnRawDataRecordedEvent += new EventHandler<RawDataEventArgs>(filter_OnRawDataRecordedEvent);
            }
        }
/**/
        
/// <summary>
        
/// 当原始数据采集到以后,入库 
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>
        void filter_OnRawDataRecordedEvent(object sender, RawDataEventArgs e)
        {
            
string allcode = e.SourceCode;//allcode就是截获的替换前的整个page页面的html
            
//WapSite.SiteDataClass wapdata = new WapSite.SiteDataClass();
            
//wapdata.WriteRawDataLog(allcode);
        }

    }

/**//// <summary>
    
/// 定义原始数据EventArgs,便于在截获完整数据后,由事件传递数据
    
/// </summary>
    public class RawDataEventArgs : EventArgs
    {
        
private string sourceCode;public RawDataEventArgs(string SourceCode)
        {
            sourceCode 
= SourceCode;
        }
        
public string SourceCode
        {
            
get { return sourceCode; }
            
set { sourceCode = value; }
        }
    }
//自定义过滤器
    public class RawFilter : Stream
    {

        Stream responseStream;

long position;
        StringBuilder responseHtml;
/**//// <summary>
        
/// 当原始数据采集成功后激发。
        
/// </summary>
        public event EventHandler<RawDataEventArgs> OnRawDataRecordedEvent;public RawFilter(Stream inputStream)
        {
            responseStream 
= inputStream;
            responseHtml 
= new StringBuilder();
        }
//实现Stream 虚方法Filter Overrides

        
public override bool CanRead
        {
            
get
            {
                
return true;
            }
        }
public override bool CanSeek
        {
            
get
            {
                
return true;
            }
        }
public override bool CanWrite
        {
            
get
            {
                
return true;
            }
        }
        
public override void Close()
        {
            responseStream.Close();
        }
public override void Flush()
        {
            responseStream.Flush();
        }
public override long Length
        {
            
get
            {
                
return 0;
            }
        }
public override long Position
        {
            
get
            {
                
return position;
            }
            
set
            {
                position 
= value;
            }
        }
public override int Read(byte[] buffer, int offset, int count)
        {
            
return responseStream.Read(buffer, offset, count);
        }
public override long Seek(long offset, SeekOrigin origin)
        {
            
return responseStream.Seek(offset, origin);
        }
public override void SetLength(long length)
        {
            responseStream.SetLength(length);
        }
//关键的点,在HttpResponse 输入内容的时候,一定会调用此方法输入数据,所以要在此方法内截获数据
        public override void Write(byte[] buffer, int offset, int count)
        {
            
string strBuffer = System.Text.UTF8Encoding.UTF8.GetString(buffer, offset, count);//采用正则,检查输入的是否有页面结束符</html>
            Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);if (!eof.IsMatch(strBuffer))
            {
              
//页面没有输出完毕,继续追加内容
                responseHtml.Append(strBuffer);
            }
            
else
            {
              
//页面输出已经完毕,截获内容
                responseHtml.Append(strBuffer);
                
string finalHtml = responseHtml.ToString();//激发数据已经获取事件
                
//OnRawDataRecordedEvent(this, new RawDataEventArgs(finalHtml));//finalHtml就是源文件内容//继续传递要发出的内容写入流
                byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(finalHtml.Replace("城管","**"));//测试 捕获的源文件内特殊字符容替换后输出

                responseStream.Write(data, 
0, data.Length);
            }
        }
    }
}

    上面就是一个httpModule的简单应用了,至于这个方案的其它方面我就不说了,也不好说,主要是大家能看得明白这个简单的httpModule应用就好,另外在web项目的里添加编译好的httpModule.dll引用,还有config里加一句<httpModules>
        <add name="OutputFilter" type="httpModuleOutputFilter.OutputFilter, httpModule" />
      </httpModules>

 测试demo下载地址 :httpModule示例下载

       转载的原文地址:查看原文