ISAPI详细分析

 ISAPI包括扩展和过滤器两种形式,都可以利用来开发动态动态Web内容。ISAPI扩展和过滤器都以DLL形式实现,供IIS进程调用。

  扩展按规范必须实现两个函数接口:GetExtensionVersionHttpExtensionProc和一个可选函数接口:TerminateExtension;扩展和Web服务器中特定虚拟目录下的文件类型关联,可以和特定的文件后缀,比如.txt关联,也可以使用通配符*和所有文件关联。比如ASP就是一个扩展,它的实现文件是asp.dll,.asp文件关联,客户端所有的对.asp文件的请求都将进入asp.dll扩展来处理。

  过滤器按规范也必须实现两个函数接口:GetFilterVersionHttpFilterProc和一个可选函数接口:TerminateFilter;过滤器分为站点级和全局级两种类型,前者只处理被装载的特定网站的事件,后者处理该IIS服务器上所有网站的事件。


ISAPI
扩展
ISAPI
扩展的可能用途

  IIS6.0之前的版本只有ISAPI过滤器能接收某特定URL的所有请求,但在6.0开始后ISAPI扩展也可以截获、改变、重定向或者拒绝对某特定URL空间的所有HTTP请求。现在ISAPI扩展基本可以实现所有过滤器的功能,并且运行得更快,效率更高。所以如非特别需要,微软推荐尽量少用过滤器。请参见过滤器用途。


ISAPI
扩展与IIS交互的典型流程


      
如果DLL不在内存中的时候,IIS装载DLL。装载DLLwindows自动调用DLL的进入,退出点函数DllMain。接着IIS调用扩展的进入点函数GetExtensionVersion。如果DLL已经装载到内存中则略过此过程。
IIS
对进入的请求做最小化预处理。
IIS
创建并填充一个EXTENSION_CONTROL_BLOCK结构来传输请求数据和回调函数指针到ISAPI扩展。
IIS
以一个为该次请求创建的EXTENSION_CONTROL_BLOCK结构指针为参数,调用ISAPI扩展的HttpExtensionProc函数。 
ISAPI
根据原始设计来完成处理工作:例如,从客户端读取更多数据(在一个POST操作中),或者写http头和数据返回客户端。
ISAPI
扩展退出HttpExtensionProc函数,通知IIS它完成了该次处理。对于同步操作,该函数返回HSE_STATUS_SUCCESS值;对于异步操作,返回HSE_STATUS_PENDING值。
如果Keep-Alive功能没有激活的话,当请求完成关闭连接后,IIS执行该次请求连接的相关清理工作。
如果ISAPI提供了TerminateExtension函数,一旦ISAPI扩展不再需要的时候,IIS调用TerminateExtension函数。如果IIS配置了缓存ISAPI扩展项,那么除非IIS服务器被关闭或重启,否则都不会调用TerminateExtension结束函数(IIS默认配置成缓存ISAPI扩展)。

注意:GetExtensionVersion函数不会每次请求时都调用,如果IIS配置了缓存ISAPI扩展选项,该函数将只调用一次。而对该扩展来说HttpExtensionProc函数则会在每次客户请求的时候被调用一次。


ISAPI
扩展的开发要点


ISAPI
扩展必须以DLL形式实现。
ISAPI
扩展必须实现两个接口函数GetExtensionVersion HttpExtensionProc;可选实现函数TerminateExtension
GetExtensionVersion
函数是进入点函数,在IIS装载该扩展时被调用一次。ISAPI扩展的初始化工作建议在GetExtensionVersion中进行,如内存分配,线程池创建,数据库连接等。也可以放在DLL的初始化函数DLLMAIN中,相关知识参见DLL初始化知识。
HttpExtensionProc
函数是功能处理进入点函数,每次有数据需要处理时会被IIS调用。这个函数接收一个EXTENSION_CONTROL_BLOCK数据结构,其中包含了要处理的数据,函数结束返回后也使用该结构和IIS通讯。
TerminateExtension
函数退出函数,当IIS卸载该DLL时被调用一次(如停止IIS),是可选实现,其中放置清理代码,如内存释放,线程池释放,数据库连接释放等。
ISAPI
扩展设计必须是线程安全的,必须处理线程同步问题,但在设计时需考虑性能问题,比如关键代码段等范围尽量小。另外在DLL的进入点和退出点DllMain函数中避免使用同步算法,比如windowswaitfor…等函数。
ISAPI
扩展中你可以创建自己的工作线程池。这个功能只有ISAPI扩展支持。
ISAPI
扩展支持异步操作。IIS支持异步读和写,所以ISAPI扩展推荐使用异步操作,这样可以最大限度利用CPU和工作线程池等。
注意 
必须牢记服务器是启动多线程来处理同时接收到的多个请求的,所以ISAPI处理函数必须是线程安全的。
IIS配置了缓存ISAPI扩展后(默认配置),GetExtensionVersion函数只会调用一次,所以初始化代码可放置在此处,如果没有配置该项就会多次调用。
ISAPI扩展中可以异步读写,可以创建自己的线程池


ISAPI
扩展的安装(以IIS6.0为例)


Dll文件拷贝到相应的虚拟目录。
IIS管理器中的"web服务扩展"中增加该扩展,并允许。
 IIS 管理器中,展开本地计算机,展开网站文件夹,右键单击所需的网站或虚拟目录,然后单击属性
单击相应的选项卡:主目录虚拟目录、或目录
应用程序设置区域中,单击配置,然后单击映射选项卡。
选择应用程序扩展或通配符扩展。 
映射选项卡上,单击添加(应用程序扩展)或插入(通配符扩展)。
可执行文件文本框中键入 DLL 的路径或单击浏览以找到该文件,如果该 DLL 文件是脚本引擎,选择应用程序引擎复选框,然后单击确定
要编辑或删除通配符应用程序映射,请进行以下操作: 
应用程序扩展列表中,单击想更改的脚本映射。
单击编辑更改脚本映射,或单击删除删除脚本映射。
要更改通配符应用程序执行的顺序,在通配符应用程序映射(执行顺序)框中重新安排通配符应用程序映射,其方法是单击上移下移按钮直到符合您想要的顺序为止。

注意:请不要在通配符应用程序映射列表中多次列出同一应用程序。

简单ISAPI扩展示例代码


ISAPI
过滤器
ISAPI
过滤器的可能用途


改变客户端发送的请求数据(URL和头)。
控制URL映射到那个具体的物理文件。
控制匿名和基础认证时使用的用户名和密码。
认证完成后修改或分析一个请求。
修改一个返回到客户端的相应。
当出现访问拒绝应答时执行相应处理。
当一个请求完成后,执行一些处理。
当客户端连接被关闭后,执行一些处理。
记录特别日志或交互分析。
执行普通认证。
处理加密和压缩。


ISAPI
过滤器与IIS交互的典型流程
IIS初始化装载一个ISAPI过滤器,它同时创建并部分填充一个HTTP_FILTER_VERSION结构。接着它调用过滤器的GetFilterVersion函数,并传输一个指向该内存的指针为参数。
ISAPI
过滤器用版本信息和描叙信息填充HTTP_FILTER_VERSION结构。最重要的是过滤器也利用该结构来定义它接收的感兴趣的通知事件,并申明过滤器的通用优先级。另外,过滤器也在此时表明它是否只对安全端口事件感兴趣或只对非安全端口事件感兴趣,或者两者都有。
在客户端浏览器和IIS服务器之间的每一次交互过程中会产生很多不同的时间。每次当一个已经注册的过滤器事件出现的时候,IIS就会调用该过滤器的HttpFilterProc进入点函数。如果多个过滤器注册个该事件,IIS将通知所有感兴趣的过滤器,通知将按照高、中、低优先级顺序来排序。如果多个过滤器申明了同一个优先级,IIS将根据过滤器在FilterLoadOrder属性中出现的顺序来通知。
ISAPI
过滤器利用IIS传输给HttpFilterProc参数中的通知类型来判断pvNotification参数指向的实际数据是什么。然后根据上下文结构内容HTTP_FILTER_CONTEXT,来做一些通用处理。
一次处理完成后,过滤器返回SF_STATUS状态中的一个给IIS,接着IIS继续处理HTTP请求和应答,知道该过滤器感兴趣的另一个通知事件出现。
Web服务被停止或卸载时,IIS调用过滤器提供的TerminateFilter函数,多数过滤器都提供改函数的实现。TerminateFilter经常用于清理和释放已分配的资源。

注意:GetFilterVersion函数确定只有在初始装载过滤器时才被调用一次。如果开发者想做每次连接的初始化工做就应该在HttpFilterProc的上下文中处理。


ISAPI
过滤器的开发要点


ISAPI
过滤器必须以DLL形式实现
ISAPI
过滤器必须提供GetFileVersionHttpFilterProc函数,TerminateFilter函数是可选实现。
GetFileterVersion
函数中需要提供版本信息和注册感兴趣的时间,在IIS装载该DLL时被调用一次,过滤器的初始化代码可放在此函数中进行。或放在dll的初始化函数DllMain中进行。
HttpFilterProc
是事件处理进入点函数,当有该过滤器感兴趣的事件时,IIS会调用该函数。
TerminateFilter
该函数在IIS卸载该过滤器时被调用(如停止IIS时),是可选实现。过滤器的清理代码可以放在此处。

过滤器事件列表事件 出现时间
SF_NOTIFY_READ_RAW_DATA Occurs when data is being read from the client. May occur more than once per request.
SF_NOTIFY_PREPROC_HEADERS Occurs immediately after IIS has pre-processed headers, but before IIS has begun to process header content.
SF_NOTIFY_URL_MAP Occurs after IIS has translated a URL to a physical path on the server.
SF_NOTIFY_AUTHENTICATION Occurs just before IIS authenticates the client.
SF_NOTIFY_ACCESS_DENIED Occurs just after IIS has determined that access is denied for the requested resource, but before IIS has sent a response to the client.
SF_NOTIFY_SEND_RESPONSE Occurs after the request has been processed by IIS, but before any headers are sent back to the client.
SF_NOTIFY_SEND_RAW_DATA Occurs as IIS sends raw data back to the client. May occur more than once per request.
SF_NOTIFY_END_OF_REQUEST Occurs at the end of the request.
SF_NOTIFY_LOG Occurs at the end of a request, just before IIS writes the transaction to the IIS log.
SF_NOTIFY_END_OF_NET_SESSION Occurs when the network session with the client is ending.

ISAPI过滤器安装(以IIS6.0为例)


 IIS 管理器中,展开本地计算机,右键单击要添加筛选器的 Web 服务器或网站,然后单击属性
单击“ISAPI 筛选器选项卡,然后单击添加 
注意 如果将筛选器添加到网站,您将无法看到从 Web 服务器的主属性继承的全局筛选器。而只能看到为网站安装的筛选器,尽管这两组筛选器都在运行。
筛选器名称文本框中,键入筛选器的名称。
可执行文件文本框中,键入 DLL 文件的名称或单击浏览以找到该文件,然后单击确定
单击向上或向下箭头以更改筛选器的装载顺序。 
注意:只能更改具有相同优先级的筛选器的加载顺序。
如果已经添加或更改了全局筛选器,则必须终止并重新启动 Web 服务器以便将新筛选器加载到内存中。在网站级别添加的筛选器将在添加时自动加载。

注意:如果 HTTP 请求触发了一个筛选器已注册的事件,则筛选器将接收包含在请求中的数据,无论该请求是针对文件、CGI 应用程序或是 ISAPI 扩展。


ISAPI过滤器的调用顺序

  当几个筛选器注册给同一事件时,将按顺序对其进行调用。优先级较高的筛选器在优先级较低的筛选器之前运行。如果几个筛选器的优先级相同,则在主属性中设置的全局筛选器将在站点级别设置的筛选器之前运行。在同一继承级别具有相同优先级的筛选器将根据其加载顺序运行。可以通过调整 Web 服务器或网站的属性来改变筛选器的加载顺序。

简单ISAPI过滤器示例代码


客户端请求的路由过程


传入的请求由安装在根网站上的任何现有的 ISAPI 过滤器处理。ISAPI 过滤器依次执行。
请求被发送到任何现有的通配符应用程序映射的应用程序,这些程序也是依次执行的。如果传入的请求是对虚拟目录中的 Web 文件进行请求的,且通配符应用程序映射已安装在了该虚拟目录和根网站上,那么只有安装在该虚拟目录的通配符应用程序映射才被执行。如果该虚拟目录上没有安装通配符应用程序映射,则将执行安装在网站上的通配符应用程序映射。换句话说,通配符应用程序映射只在所请求的 Web 文件所处的应用程序中不存在映射时才会被继承。
IIS 
服务器会查看应用程序映射表,以确定由哪个 ISAPI 应用程序或 CGI 脚本专门处理所请求的文件。
每个阶段都可以附加响应,然后传回给客户端。


ISAPI
扩展、过滤器和Asp.dll的关系


Asp.dll
是一个典型的应用程序扩展。
扩展可以针对虚拟目录层次,过滤器只能到网站层次。
每个虚拟目录中一种类型的后缀文件只能映射一个应用程序扩展,如.asp文件只能映射asp.dll扩展。
针对每个虚拟目录可以设置多个通配符扩展,统配付扩展按优先级在应用程序扩展之前执行。
过滤器是事件驱动,根据注册的事件种类不同,调用的时机也将不一样,可以在通配符扩展、应用程序扩展(包括asp.dll)之前也可以在之后被调用。请参见过滤器事件列表。


ISAPI
扩展和过滤器比较
相同点

两者都可以达到很多相同的目的。
因为IIS处理客户端请求是多线程的,所以两者的处理函数入口都是多线程,处理函数都必须是线程安全的。
都以DLL形式实现,一般都导出三个规定的接口函数。
都被IIS统一调度,扩展IIS的功能。
从实现上来说,在两者的DLL中都可以创建自己的工作线程,但由于扩展支持异步操作所以能最大限度发挥多线程的作用。
不同点
过滤器只访问头,不能访问请求主体。
过滤器只能在每个站点配置,而不能在每个虚拟目录配置;而扩展可以。
过滤器不应包含长期运行的操作,因为 ISAPI 过滤器是同步进行的;而扩展支持异步操作。
过滤器灵活性较小,因为 ISAPI 过滤器 API 的功能比 ISAPI 扩展 API 少,后者用于编写 ISAPI 应用程序。
过滤器在时间上难以管理。
过滤器是事件驱动的。
扩展可以显式调用,比如:http://Server_name/asp.dll/test.asp;过滤器不可以。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值