巴布鱼——软件工程师的家园

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 4580|回复: 0
打印 上一主题 下一主题

[C/C++] 编写自己的ISAPI过滤器

[复制链接]

40

主题

41

帖子

356

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
356
QQ
跳转到指定楼层
楼主
发表于 2015-4-22 18:01:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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事件,以便在每次网络会话结束时就释放资源,这样可以减轻服务器的负荷。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|巴布鱼

GMT+8, 2024-4-27 05:13 , Processed in 0.072265 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表