设为首页 收藏本站
查看: 1313|回复: 0

[经验分享] IIS筛选器编程

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-4-6 09:53:40 | 显示全部楼层 |阅读模式
基于Vc++开发IIS7以及IIS6的万能筛选器


一、iis6篇

1)新建工程:准备好vs6以后,新建新工程,选择"ISAPI Filter Wizard" 工程类型,一路下一步之后,工程目录就出来了(暂时将我们初始化的filter类命令为CTestFilter)。
2)打开vs初始化的工程,打开CTestFilter.cpp文件,我们可以看到有一个自动生成的函数:
BOOL CTestFilter::GetFilterVersion(PHTTP_FILTER_VERSION pVer)
{
// Call default implementation for initialization
CTestFilter::GetFilterVersion(pVer);

// Clear the flags set by base class
pVer->dwFlags &= ~SF_NOTIFY_ORDER_MASK;

// Set the flags we are interested in
pVer->dwFlags |= SF_NOTIFY_ORDER_HIGH| SF_NOTIFY_PREPROC_HEADERS | SF_NOTIFY_SEND_RAW_DATA;

// Load description string
TCHAR sz[SF_MAX_FILTER_DESC_LEN+1];
ISAPIVERIFY(::LoadString(AfxGetResourceHandle(),
IDS_FILTER, sz, SF_MAX_FILTER_DESC_LEN));
_tcscpy(pVer->lpszFilterDesc, sz);
return TRUE;
}
不要关注其他代码,只需要关注红色字体部分,这几个系统常量是用来指定筛选器需要拦截哪些http内容的,我简单拦截类型有好几种,详细信息可以查询msdn的文档,我只简单介绍下其中的SF_NOTIFY_PREPROC_HEADERS和 SF_NOTIFY_SEND_RAW_DATA,SF_NOTIFY_PREPROC_HEADERS代表在iis处理http的header请求时触发一次拦截,而SF_NOTIFY_SEND_RAW_DATA代表在iis向客户端回写http的response内容前触发拦截,在这个拦截当中,你可以接收到response的指针,修改response的内容。
3)还是用wizard,去实现CHttpFilter基类的各个拦截方法(需要与前面的GetFilterVersion方法中指定的拦截事件对应,否则iis不会触发这些方法的),这里我还是介绍下与上一步向对应的OnSendRawData(CHttpFilterContext* pfc, PHTTP_FILTER_RAW_DATA pRawData)和OnPreprocHeaders(CHttpFilterContext* pfc,PHTTP_FILTER_PREPROC_HEADERS pHeaders)两个函数,大家可以很容易地看出这两个函数与前面两个拦截类型的对应关系。OnPreprocHeaders是专门用来在iis处理http请求前,对客户端的http header进行处理,其中入参pHeaders是个结构型数据,其中包含了一个指向header对象的指针,我们可以拿到这个指针进行预处理,并可以修改headers的内容。
OnSendRawData可以说是这些方法中最强悍的了,它可以拿到iis的response内容,并可以修改response的内容,其中pRawData这个结构型的入参就包含了response内容的指针,还是上代码给大家讲讲这个函数是如何去修改一切的吧:
DWORD CTestFilter::OnSendRawData(CHttpFilterContext* pfc, PHTTP_FILTER_RAW_DATA pRawData)
{
// TODO: Add your specialized code here and/or call the base class
CString resp="Hello isapi!!";
void* mem=(void*)pfc->AllocMem(resp.GetLength());//必须使用isapi提供的申请内存方法,才能正常返回http内容,用isapi的方法申请的内存,iis会自动帮你回收
memset(mem,0,resp.GetLength());
memcpy(mem,resp.GetBuffer(0),resp.GetLength());
pRawData->cbInBuffer=resp.GetLength();
pRawData->cbInData=resp.GetLength();
pRawData->pvInData=mem;
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
这样修改过后,所有客户端的请求都变成了”Hello isqpi!!“了,而且连正常的http头都被去掉了。
4)部署:编译完成刚才的工程后,我们可以得到一个TestFilter.dll的文件,打开iis6的管理页面,进入web站点的属性对话框,到isapi的选项卡中,添加我们刚才生成的dll文件,并重启iis服务器,ok,iis就只会返回”Hello isapi!!“了。
095600452.png


二、iis7篇
伴随着windows server2008的出现,iis7也一起推出,iis7虽然也可以通过很曲折的方式,实现isapi接口功能,但根据实践的情况来开,iis7在使用isapi扩展来实现拦截功能时,经常会出现拦截不了的烦人问题,这时我们在查阅了大量资料后发现,iis7对isapi的支持本来就不好,因为微软又在iis7这个平台上推出了一个更强大的拦截实现,那就是iis扩展模块,iis7的所有功能都是通过加载不同的模块来实现的,而且为我们实现拦截器特别提供了一个httpmodule的模块,这个模块是凌驾于所有http请求的,不管你使用的asp还是asp.net甚至是借用iis做服务器的php服务器,所有的请求都会先经过这个模块来处理,难怪微软不会去关注iis7对isapi的兼容问题,它要推新东西了嘛~
下面我们就介绍下如何通过iis的模块来实现拦截并修改http请求的功能:
1)环境准备:visual studio2008/2005+iis7+windows server2008。
2)新建c++工程:在vs中新建一个空的动态链接库的工程。
3)新建一个CHttpModule的子类CMyHttpModule(需要基于对头文件httpserv.h的引用),并实现一个虚方法OnBeginRequest:
#define _WINSOCKAPI_
#include
#include
#include
class CMyHttpModule: public CHttpModule
{
public:
REQUEST_NOTIFICATION_STATUS
OnBeginRequest(
IN IHttpContext * pHttpContext,
IN IHttpEventProvider * pProvider
)
{
UNREFERENCED_PARAMETER( pProvider );
// 创建一个 HRESULT 来接收方法返回值.
HRESULT hr;
// 获取一个指向response对象的指针.
IHttpResponse * pHttpResponse = pHttpContext->GetResponse();
if (pHttpResponse != NULL)
{
// 直接清理掉原来的response内容.
pHttpResponse->Clear();
// 设置response的格式.
pHttpResponse->SetHeader(
HttpHeaderContentType,"text/plain",
(USHORT)strlen("text/plain"),TRUE);
PCSTR pszBuffer = "Hello HttpModule!!!";
// 创建一个数据块.
HTTP_DATA_CHUNK dataChunk;
// 把数据块类型设置成http类型的(后续的内存清理工作就会由iis容器自己完成).
dataChunk.DataChunkType = HttpDataChunkFromMemory;
DWORD cbSent;
// 给数据块赋值.
dataChunk.FromMemory.pBuffer =
(PVOID) pszBuffer;
dataChunk.FromMemory.BufferLength =
(USHORT) strlen(pszBuffer);
// 将数据块插入到response内容中.
hr = pHttpResponse->WriteEntityChunks(
&dataChunk,1,FALSE,TRUE,&cbSent);
if (FAILED(hr))
{
pHttpResponse->SetStatus(500,"Server Error",0,hr);
}
return RQ_NOTIFICATION_FINISH_REQUEST;
}
return RQ_NOTIFICATION_CONTINUE;
}
}
4)新建一个实现了IHttpModuleFactory接口的工厂类,用来注册拦截模块和拦截的方式
class CMyHttpModuleFactory : public IHttpModuleFactory
{
public:
HRESULT
GetHttpModule(
OUT CHttpModule ** ppModule,
IN IModuleAllocator * pAllocator
)
{
UNREFERENCED_PARAMETER( pAllocator );
// 实例化一个模块的指针.
CMyHttpModule * pModule = new CMyHttpModule;
if (!pModule)
{
return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
}
else
{
*ppModule = pModule;
pModule = NULL;
return S_OK;
}
}
void
Terminate()
{
// 清理自己的内存.
delete this;
}
};
// 用来注册模块工厂的方法.
HRESULT
__stdcall
RegisterModule(
DWORD dwServerVersion,
IHttpModuleRegistrationInfo * pModuleInfo,
IHttpServer * pGlobalInfo
)
{
UNREFERENCED_PARAMETER( dwServerVersion );
UNREFERENCED_PARAMETER( pGlobalInfo );
// 设置需要拦截的方式,这里设置的是给客户端返回response内容前,和我们之前iis6的示例类似,可以设置多个,但必须和你的httpmodule中对应.
return pModuleInfo->SetRequestNotifications(
new CMyHttpModuleFactory,
RQ_BEGIN_REQUEST,
0
);
}
5)编译并生成一个MyHttpModule.dll的动态链接库,将保存MyHttpModule.dll的全路径添加到%windir%system32inetsrvconfigapplicationHost.config文件的globalModules节点下,重启iis,ok,这下访问你iis中的任何一个文件,返回的内容都会是:“Hello HttpModule!!!”。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-200337-1-1.html 上篇帖子: IIS网站设置SSL加密机制 下篇帖子: WEB服务器虚拟主机IIS防范入侵
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

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