CAN I WRITE AN ISAPI FILTER USING MANAGED CODE?

本文第一部分转载自 :

http://blogs.msdn.com/david.wang/archive/2006/02/09/Can_I_write_an_ISAPI_Filter_using_Managed_Code.aspx

 

Question:

Hi,

Is it possible to write an ISAPI filter equivalent (IHttpModule imlementation?) using managed code? I want my filter to get invoked for non .NET applications a well.

thanks

Answer:

Unfortunately, you cannot [yet] write an ISAPI Filter equivalent using managed code. The closest you can get on existing technologies is IIS6+ASP.Net 2.0 configured as Wildcard Application Mapping, which allows managed code (either HttpModule or HttpHandler) to be invoked for any request type (.NET as well as non .NET) and optionally use the DefaultHttpHandler to pass the request handling back to IIS for further processing. For example, this allows .NET Forms Authentication to apply for ASP pages.

However, I do not consider this to be really "ISAPI Filter equivalent", by which I mean invoking managed code throughout the request processing lifecycle. Managed code is only invoked in one place in the request pipeline, right before the request is processed and executed. Meanwhile, ISAPI Filter has over a dozen different events firing throughout the request lifecycle, one of which corresponds to "right before the request is processed and executed".

Of course, you can always write an ISAPI DLL in native code which basically parses the request, launches the CLR inside an AppDomain, and passes requests into it for processing. This is how ASP.Net works today. Or you can write an ISAPI DLL which uses COM Interop to call into managed code components. You may even do a lot of work and write an ISAPI Filter DLL which triggers on all events and passes data into the AppDomain to "simulate" managed code running inside of ISAPI Filter events. But none of these are really "ISAPI Filter equivalent" with managed code.

In other words, it is not possible to use managed code to customize authentication events - IIS negotiates Basic/NTLM/Kerberos/Passport authentication prior to processing and executing the request, which also preceeds when the ASP.Net Wildcard Application Mapping is executed... thus it is not possible for managed code to participate in modifying the IIS authentication behavior. This is why you must configure IIS to be "Anonymous Only" in order to apply .NET Forms Authentication.

Now, IIS7 presents a different story. You will have ISAPI Filter equivalent extensibility of IIS7 using managed code, and it is using the familiar IHttpModule and IHttpHandler interfaces. What we did in IIS7 is refactor and componentize the IIS6 Web Server into a compact "IIS7 Server Core" which exposes a brand new native code extensibility interface, and we are providing 40+ "Functionality Modules" which are coded using the new native code extensibility interface. The 40+ "Functionality Modules" allow the "IIS7 Server Core" to provide the "IIS6 feature set" plus expose completely new features and functionality. One of them is extensibility of the IIS7 Server Core using managed code in an integrated fashion.

Finally, a word of caution when attempting to use managed code to "filter" requests, regardless of IIS version. Since only one CLR Version can be in a given process, if you configure managed code of one version to "filter" requests that are ultimately executed with another CLR Version, that will cause a conflict and prevent request execution.

//David

Filed under: ISAPI, IIS, IIS 7.0 (beta)

 

千言万语汇成下面一句话

Microsoft simply does not provide any way to extend IIS behavior with a managed code "ISAPI" interface. You will have to wait for IIS7 for the ability

 

在IIS7 中(Vista和windows server 2008),支持ISAPI Filter,但默认并没有安装, 需要通过以下的方式进行安装

IIS CGI

 

需要说明一下ISAPI扩展和ISAPI筛选器的区别

1. ISAPI筛选器(这是应用到网站级别的,它可以直接接管所有的请求,并做相应的处理)

image

2. ISAPI扩展(这是由IIS接管到之后,后续进一步细化的设计,即具体某种文件该如何处理)

image

我们最熟知的就是所有与ASP.NET有关的请求都将交给aspnet_isapi.dll进行处理

然后,再往下面就是我们知道的httpModule和httpHandler了

page525_0.jpg

 

这里还要说一下IIS 7和IIS 6的一些区别

在之前的 IIS,ASP.NET 是以 IIS ISAPI extension 的方式实作而外加到 IIS,其实包括 ASP 以及 PHP,也都以相同的方式实作(PHP 在 IIS 采用了两种实作方式,除了 IIS ISAPI extension 的方式,也包括了 CGI 的方式,系统管理者能选择 PHP 程序的执行方式),因此客户端对 IIS 的 HTTP 要求会先经由 IIS 处理,然后 IIS 根据要求的内容类型,如果是 HTML 静态网页就由 IIS 自行处理,如果不是,就根据要求的内容类型,分派给各自的 IIS ISAPI extension;如果要求的内容类型是 ASP.NET,就分派给负责处理 ASP.NET 的 IIS ISAPI extension,也就是 aspnet_isapi.dll。图四是这个架构的示意图。

圖四:IIS 6 的執行架構(圖片來源:www.iis.net)

而 IIS 7 完全整合 .NET 之后,架构的处理顺序有了很大的不同(如图五),最主要的原因就是 ASP.NET 从 IIS 外挂程序(ISAPI extension)的角色,进入了 IIS 核心,而且也能以 ASP.NET 模块负责处理 IIS 7 的诸多类型要求。这些 ASP.NET 模块不只能处理 ASP.NET 网页程序,也能处理其它如 ASP 程序、PHP 程序或静态 HTML 网页,也因为 ASP.NET 的诸多功能已经成为 IIS 7 的一部份,因此 ASP 程序、PHP 程序或静态 HTML 网页等类型的要求,也能使用像是窗体认证(Forms Authentication)或输出快取(Output Cache)等 ASP.NET 2.0 的功能(但须修改 IIS 7 的设定值)。也因为 IIS 7 允许自行以 ASP.NET API 开发并加入模块,因此 ASP.NET 网页开发人员将更容易扩充 IIS 7 和网站应用程序的功能,甚至能自行以 .NET 编写管理 IIS 7 的程序(例如以程控 IIS 7 以建置网站或虚拟目录)。

圖五:IIS 7 的執行架構(圖片來源:www.iis.net)

 

也就是说,如果网站确信就是ASP.NET的,那么当然可以直接用ASP.NET的引擎处理,而不需要经过任何其他的过滤了

 

虽然 IIS 7 提供了新的 .NET 整合模式,但还是保留了传统的 ASP.NET 执行模式,因为某些 ASP.NET 网站应用程序在新的 .NET 整合模式执行,可能会有兼容性的问题,如果真的发生,除了找出、修改造成兼容性的问题,也可以让 ASP.NET 网站应用程序继续以传统的 ASP.NET 模式执行。而不论新的 .NET 整合模式,或者传统的 ASP.NET 执行模式,都是 IIS 7 应用程序集区的 Managed pipeline mode 设定值,因此,若要让 ASP.NET 网站应用程序以传统的 ASP.NET 模式执行,就是将 ASP.NET 网站应用程序放到属性为传统 ASP.NET 模式的应用程序集区。

Windows Vista RC1 的 IIS 7 预设建了两个应用程序集区,分别是 Class .NET AppPool 和 DefaultAppPool,前者是传统 ASP.NET 模式,后者是新的 .NET 整合模式。如果要让 ASP.NET 网站应用程序继续以传统的 ASP.NET 模式执行,就是将 ASP.NET 网站应用程序指定给传统的 ASP.NET 模式的应用程序集区,例如 Class .NET AppPool(如图六),或者是您自建的传统 ASP.NET 模式应用程序集区。

圖六:指定網站應用程式的應用程式集區

 

另外,蝈蝈(csdn的郭红俊)有一篇博客专门比较了三个IIS版本对于ASP.NET的处理

http://blog.csdn.net/ghj1976/archive/2008/07/25/2710120.aspx

IIS 5 的 ASP.net 请求处理过程

o_8001.gif

对图的解释:

IIS 5.x 一个显著的特征就是 Web Server 和真正的 ASP.NET Application 的分离。作为 Web Server 的IIS运行在一个名为 InetInfo.exe 的进程上,InetInfo.exe 是一个Native Executive,并不是一个托管的程序,而我们真正的 ASP.NET Application 则是运行在一个叫做 aspnet_wp 的 Worker Process 上面,在该进程初始化的时候会加载CLR,所以这是一个托管的环境。

ISAPI:  指能够处理各种后缀名的应用程序。 ISAPI 是下面单词的简写 :Internet Server Application Programe Interface,互联网服务器应用程序接口。

IIS 5 模式的特点:

1、首先,同一台主机上在同一时间只能运行一个 aspnet_wp 进程,每个基于虚拟目录的 ASP.NET Application 对应一个 Application Domain ,也就是说每个 Application 都运行在同一个 Worker Process 中,Application之间的隔离是基于 Application Domain 的,而不是基于Process的。

2、其次,ASP.NET  ISAPI 不但负责创建 aspnet_wp Worker Process,而且负责监控该进程,如果检测到 aspnet_wp 的 Performance 降低到某个设定的下限,ASP.NET  ISAPI 会负责结束掉该进程。当 aspnet_wp 结束掉之后,后续的 Request 会导致ASP.NET ISAPI 重新创建新的 aspnet_wp Worker Process。

3、最后,由于 IIS 和 Application 运行在他们各自的进程中,他们之间的通信必须采用特定的通信机制。本质上 IIS 所在的 InetInfo 进程和 Worker Process 之间的通信是同一台机器不同进程的通信(local interprocess communications),处于Performance的考虑,他们之间采用基于Named pipe的通信机制。ASP.NET ISAPI和Worker Process之间的通信通过他们之间的一组Pipe实现。同样处于Performance的原因,ASP.NET ISAPI 通过异步的方式将Request 传到Worker Process 并获得 Response,但是 Worker Process 则是通过同步的方式向 ASP.NET ISAPI 获得一些基于 Server 的变量。

IIS6 的 ASP.net 请求处理过程

o_8002.gif

对图的解释:

IIS 5.x 是通过 InetInfo.exe 监听 Request 并把Request分发到Work Process。换句话说,在IIS 5.x中对Request的监听和分发是在User Mode中进行,在IIS 6中,这种工作被移植到kernel Mode中进行,所有的这一切都是通过一个新的组件:http.sys 来负责。

注:为了避免用户应用程序访问或者修改关键的操作系统数据,windows提供了两种处理器访问模式:用户模式(User Mode)和内核模式(Kernel Mode)。一般地,用户程序运行在User mode下,而操作系统代码运行在Kernel Mode下。Kernel Mode的代码允许访问所有系统内存和所有CPU指令。

在User Mode下,http.sys接收到一个基于 aspx 的http request,然后它会根据IIS中的 Metabase 查看该基于该 Request 的 Application 属于哪个Application Pool, 如果该Application Pool不存在,则创建之。否则直接将 request 发到对应Application Pool 的 Queue中。

每个 Application Pool 对应着一个Worker Process:w3wp.exe,毫无疑问他是运行在User Mode下的。在IIS Metabase 中维护着 Application Pool 和worker process的Mapping。WAS(Web Administrative service)根据这样一个mapping,将存在于某个Application Pool Queue的request 传递到对应的worker process(如果没有,就创建这样一个进程)。在 worker process 初始化的时候,加载ASP.NET ISAPI,ASP.NET ISAPI 进而加载CLR。最后的流程就和IIS 5.x一样了:通过AppManagerAppDomainFactory 的 Create方法为 Application 创建一个Application Domain;通过 ISAPIRuntime 的 ProcessRequest处理Request,进而将流程进入到ASP.NET Http Runtime Pipeline。

IIS 7  的 ASP.net 请求处理过程

IIS7 站点启动并处理请求的步骤如下图:

步骤 1 到 6 ,是处理应用启动,启动好后,以后就不需要再走这个步骤了。

o_9010.jpg

上图的8个步骤分别如下:

1、当客户端浏览器开始HTTP 请求一个WEB 服务器的资源时,HTTP.sys 拦截到这个请求。
2、HTTP.sys contacts WAS to obtain information from the configuration store.

3、WAS 向配置存储中心请求配置信息。applicationHost.config。
4、WWW 服务接受到配置信息,配置信息指类似应用程序池配置信息,站点配置信息等等。
5、WWW 服务使用配置信息去配置 HTTP.sys 处理策略。
6、WAS starts a worker process for the application pool to which the request was made.

7、The worker process processes the request and returns a response to HTTP.sys.

8、客户端接受到处理结果信息。

W3WP.exe 进程中又是如果处理得呢?? IIS 7 的应用程序池的托管管道模式分两种: 经典和集成。 这两种模式下处理策略各不相通。

 

IIS 6 以及 IIS7 经典模式的托管管道的架构

       在IIS7之前,ASP.NET 是以 IIS ISAPI extension 的方式外加到 IIS,其实包括 ASP 以及 PHP,也都以相同的方式配置(PHP 在 IIS 采用了两种配置方式,除了 IIS ISAPI extension 的方式,也包括了 CGI 的方式,系统管理者能选择 PHP 程序的执行方式),因此客户端对 IIS 的 HTTP 请求会先经由 IIS 处理,然后 IIS 根据要求的内容类型,如果是 HTML 静态网页就由 IIS 自行处理,如果不是,就根据要求的内容类型,分派给各自的 IIS ISAPI extension;如果要求的内容类型是 ASP.NET,就分派给负责处理 ASP.NET 的 IIS ISAPI extension,也就是 aspnet_isapi.dll。下图是这个架构的示意图。

IIS  7 应用程序池的 托管管道模式  经典  模式也是这样的工作原理。 这种模式是兼容IIS 6 的方式, 以减少升级的成本。

o_9003.jpg

IIS6 的执行架构图,以及 IIS7  应用程序池配置成经典模式的执行架构图

IIS  7 应用程序池的 托管管道模式  集成模式

       而 IIS 7 完全整合 .NET 之后,架构的处理顺序有了很大的不同(如下图),最主要的原因就是 ASP.NET 从 IIS 插件(ISAPI extension)的角色,进入了 IIS 核心,而且也能以 ASP.NET 模块负责处理 IIS 7 的诸多类型要求。这些 ASP.NET 模块不只能处理 ASP.NET 网页程序,也能处理其他如 ASP 程序、PHP 程序或静态 HTML 网页,也因为 ASP.NET 的诸多功能已经成为 IIS 7 的一部份,因此 ASP 程序、PHP 程序或静态 HTML 网页等类型的要求,也能使用像是Forms认证(Forms Authentication)或输出缓存(Output Cache)等 ASP.NET 2.0 的功能(但须修改 IIS 7 的设定值)。也因为 IIS 7 允许自行以 ASP.NET API 开发并加入模块,因此 ASP.NET 网页开发人员将更容易扩充 IIS 7 和网站应用程序的功能,甚至能自行以 .NET 编写管理 IIS 7 的程序(例如以程控 IIS 7 以建置网站或虚拟目录)。

o_9004.jpg

IIS 7 的执行架构图(集成托管信道模式下的架构)

小结

IIS5 到 IIS6 的改进,主要是 HTTP.sys 的改进。

IIS6 到 IIS7 的改进,主要是 ISAPI 的改进。

 

【附录】另外一个用C++编写Filter的例子

http://qzone.qq.com/blog/619685283-1231913924

编写ISAPI FILTER,在IIS向浏览器发送反馈之前,替换掉.NET的输出内容。该演示使用VC6.0+IIS5.0+WINXP SP2
假设我们想把yahoo.com替换为im286.com,其原文件为:
复制内容到剪贴板
代码:
<html>
<body>
<A HREF="http://www.yahoo.com">http://www.yahoo.com</A>
</body>
</html>
1、新建工程,选择ISAPI Extension Wizard,项目名称假设就叫:bababian
54518531217859.jpg
2、在向导中第一步,选择Generate a Filter object
54518539025739.jpg
3、在向导中第一步,选择Outgoing raw data and headers
54518542133328.jpg
2008-7-20 22:10:16
4、创建了工程后,我们选择OnSendRawData进行处理,代码如下:
复制内容到剪贴板
代码:
DWORD CBababianFilter::OnSendRawData(CHttpFilterContext* pCtxt,
PHTTP_FILTER_RAW_DATA pRawData)
{
char* pchIn = (char*)pRawData->pvInData;
for(DWORD cbBuffer=0; cbBuffer<pRawData->cbInData;cbBuffer++){
if((pchIn[cbBuffer]=='y')&&
(pchIn[cbBuffer+1]=='a')&&
(pchIn[cbBuffer+2]=='h')&&
(pchIn[cbBuffer+3]=='o')&&
(pchIn[cbBuffer+4]=='o')){
pchIn[cbBuffer]='i';
pchIn[cbBuffer+1]='m';
pchIn[cbBuffer+2]='2';
pchIn[cbBuffer+3]='8';
pchIn[cbBuffer+4]='6';
}
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
5、编译后,在IIS里加载该FILTER,然后重新启动IIS。
54518546846582.jpg
6、在浏览器里察看效果。
54518554659497.jpg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值