ISAPI过滤器简介

ISAPI是Internet Server Application Programming Interface 的简称,ISAPI过滤器是IIS进程内的DLL(进程名为inetinfo),它在web服务启动时被加载,服务停止时退出。
IASPI过滤器可以用来定制认证过程、压缩、加密、流量分析、请求分析、请求过滤等等,从某种意义上来说,ISAPI过滤器可以被看作是对IIS进行定制和优化的工具。
ISAPI过滤器的基本工作原理是基于事件触发的单线程过滤器,一个标准的ISAPI过滤器由以下几个部分组成:
1、过滤器初始化
2、消息接收过滤
3、事件处理
4、退出处理

过滤器初始化一般是设置版本信息、优先级、消息过滤器,这些工作在GetFilterVersion中完成,例如:
BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
{
pVer->dwFilterVersion = HTTP_FILTER_REVISION;
lstrcpy(pVer->lpszFilterDesc, “Filter Shotgun”);
pVer->dwFlags = SF_NOTIFY_ORDER_DEFAULT | SF_NOTIFY_URL_MAP;
return TRUE;
}
上面这段程序设置版本信息为”Filter Shotgun”,程序的优先级为默认(SF_NOTIFY_ORDER_DEFAULT),过滤器程序在映射文件物理地址时工作( SF_NOTIFY_URL_MAP)
其中,消息过滤允许关注以下的事件:
SF_NOTIFY_READ_RAW_DATA 读取数据
SF_NOTIFY_SEND_RAW_DATA 发送数据
SF_NOTIFY_END_OF_REQUEST 结束请求
SF_NOTIFY_PREPROC_HEADERS 任何一个HTTP头都会触发这个事件
SF_NOTIFY_URL_MAP 这个事件在IIS将web路径映射为物理路径时发生
SF_NOTIFY_AUTHENTICATION 开始认证
SF_NOTIFY_AUTH_COMPLETE 认证结束
SF_NOTIFY_SEND_RESPONSE 发送回应
SF_NOTIFY_LOG 产生日志
SF_NOTIFY_END_OF_NET_SESSION 结束会话

事件之间用 | 连接,当系统发生了ISAPI过滤器程序所关注的事件时,IIS会传送一个NotificationType的变量给HttpFilterProc函数,由该函数判断事件的类型并调用响应的处理函数。
DWORD WINAPI __stdcall HttpFilterProc( HTTP_FILTER_CONTEXT * pfc,DWORD NotificationType, VOID * pvData )
{
switch ( NotificationType )
{
case SF_NOTIFY_PREPROC_HEADERS:
return OnPreprocHeaders(pfc, (PHTTP_FILTER_PREPROC_HEADERS)pvData);
case SF_NOTIFY_URL_MAP:
return OnUrlMap(pfc, (PHTTP_FILTER_URL_MAP)pvData );
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
事件处理函数可以通过服务器支持的函数调用对url, header, path等参数进行处理,例如,我们需要截获所有的值为Shotgun.com的HOST头并替换为Shotgun.net,就可以通过GetHeader和SetHeader函数来实现:
DWORD inline OnPreprocHeaders(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pvData)
{ char Host[1024];
DWORD cb;
cb=sizeof(Host);
pvData->GetHeader(pfc,”Host:”,Host,&cb);
if(!_strnicmp(Host,”Shotgun.com”,5))
pvData->SetHeader(pfc,”Host”,”Shotgun.net”);
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}

事件处理函数可以返回以下的值:
SF_STATUS_REQ_FINISHED 过滤器接管了HTTP请求,服务器可以断开会话。
SF_STATUS_REQ_FINISHED_KEEP_CONN 过滤器接管了HTTP请求。但是服务器需要保持TCP会话。
SF_STATUS_REQ_NEXT_NOTIFICATION 正常的返回,IIS将调用消息队列中的下一个过滤器。
SF_STATUS_REQ_HANDLED_NOTIFICATION 过滤器接管了这个消息,这种事件不需要再通知其他的句柄。
SF_STATUS_REQ_ERROR 错误返回,服务器应该调用GetLastError,并且将错误信息返回给客户端。
SF_STATUS_REQ_READ_NEXT 过滤器是不透明的流过滤器(加密/压缩HTTP请求)会话参数已经通过。这个返回仅当使用RAW-READ事件处理时有效,这个消息指出请求并没有全部完成,服务器需要继续进行读操作并再次通知过滤器。
服务器支持的函数通过一个HTTP_FILTER_CONTEXT或者HTTP_FILTER_PREPROC_HEADERS 结构调用:
1、GetHeader 取得HTTP头
2、SetHeader 设置HTTP头
3、AddHeader 增加HTTP头
4、AddResponseHeaders 增加返回给用户的HTTP头
5、AllocMem 分配内存
6、GetServerVariable 取得服务器变量
7、WriteClient 直接往客户端写数据
8、ServerSupportFunction 支持以下多种灵活的功能:
SF_REQ_ADD_HEADERS_ON_DENIAL 这个功能允许过滤器在服务器产生拒绝访问的
事件时增加特定的HTTP头,此函数一般用于认证过滤器
SF_REQ_DISABLE_NOTIFICATIONS 禁止某个事件消息
SF_REQ_GET_CONNID 这个功能在IIS4.0以后的版本已不再支持
SF_REQ_GET_PROPERTY 取得IIS属性
SF_REQ_NORMALIZE_URL 规整URL
SF_REQ_SEND_RESPONSE_HEADER 发送回应HTTP头
SF_REQ_SET_NEXT_READ_SIZE 设置下次数据读尺寸
SF_REQ_SET_PROXY_INFO 设置代理信息

当ISAPI过滤器卸载时,TerminateFilter将会被调用,在这个函数中,你需要释放过滤器申请的所有资源,值得注意的是。微软推荐关注SF_NOTIFY_END_OF_NET_SESSION事件,以便在每次网络会话结束时就释放资源,这样可以减轻服务器的负荷。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注