使用ISAPI過濾器增強IIS的功能
發表于:2007-07-14來源:作者:點擊數:
標簽:
復旦大學計算機科學系 林 海 作為一個WWW 服務器 軟件,微軟公司的Inte .net Infomation Server(IIS)簡單易 學,管理方便,得到了廣泛的使用。您還可以通過ISAPI過濾器,進行自己定制的處 理,來增強IIS的功能。ISAPI過濾器可以定制以下的處理:接收HTTP協
復旦大學計算機科學系 林 海
作為一個WWW
服務器軟件,微軟公司的Inte
.net Infomation Server(IIS)簡單易
學,管理方便,得到了廣泛的使用。您還可以通過ISAPI過濾器,進行自己定制的處
理,來增強IIS的功能。ISAPI過濾器可以定制以下的處理:接收HTTP協議頭預處理、
發送HTTP協議頭預處理、發送生數據預處理、獲得生數據預處理、HTTP會話結束信息
處理、自定義的
安全認證機制、URL映射信息處理、日志記錄處理等。靈活利用這些定
制處理,您可以完成許多看似難以實現的功能,得到意想不到的效果。但是ISAPI過濾
器使用不當也會影響服務器的
性能。
ISAPI過濾器的
開發非常簡單,只需要完成三個接口DLL函數即可。它們是
GetFilterVersion()、HttpFilterProc()、TerminateFilter(),大家可以查看MSDN
了解詳細的用法。ISAPI過濾器是DLL文件,一般用C/C++語言開發。為使ISAPI過濾器
能夠運行,您需要在注冊表的
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\W3SVC\Parameters下建
立一個字符串項,其名稱為"Filter Dlls",值為ISAPI過濾器文件的全路徑名稱。若
這個字符串項已經存在,只需把它的全路徑名稱加入其中,不同的ISAPI過濾器文件
之間用";"分隔,您可以根據執行的優先順序加在適當的位置。設置好后重新啟動IIS
服務,您的ISAPI過濾器就發揮作用了。
下面作者舉二個具體的應
用例子。
一、虛擬主機WWW站點的實現
所謂虛擬主機WWW站點,是指不同的域名占用同一個IP地址,各自擁有自己的主頁。
這樣您可以在同一臺機器上為幾個甚至幾十個公司建立各自的WWW站點。IIS 3.0不
提供虛擬主機WWW站點的功能,但是我們可以通過ISAPI過濾器來實現它。其原理是
通過URL映射信息處理,將不同的域名重新映射到不同的物理文件。
下面是它的源程序。
fmulti.def:
LIBRARY fmulti
E
XPORTS GetFilterVersion
HttpFilterProc
TerminateFilter
fmulti.c:
#include <stdio.h>
#include <string.h>
#include <
windows.h>
#include <httpfilt.h>
#define baseroot "C:\\InetPub\\wwwroot\\"
BOOL WINAPI GetFilterVersion(HTTP_FILTER_VERSION *pVer)
{
pVer->dwFilterVersion = HTTP_FILTER_REVISION;
strcpy(pVer->lpszFilterDesc, "fmulti");
pVer->dwFlags = SF_NOTIFY_URL_MAP | SF_NOTIFY_ORDER_HIGH;
/* 過濾的內容 */
return TRUE;
}
DWORD WINAPI HttpFilterProc(HTTP_FILTER_CONTEXT *pfc,
DWORD noteType,
VOID *pvNote)
{
DWORD namelen = 256;
char svrname[256];
char phyfile[280];
*svrname = 0;
(pfc->GetServerVariable)(pfc, "SERVER_NAME",svrname, &namelen);
_strlwr(svrname);
strcpy(phyfile,
((PHTTP_FILTER_URL_MAP)pvNote)->pszPhysicalPath + strlen(baseroot));
/* 以下根據域名設置需訪問的物理文件 */
if (strcmp(svrname, "ca.best.net")==0)
{
sprintf(((PHTTP_FILTER_URL_MAP)pvNote)->pszPhysicalPath,
"C:\\InetPub\\caroot\\%s",
phyfile);
}
else if (strcmp(svrname, "cb.best.net")==0)
{
sprintf(((PHTTP_FILTER_URL_MAP)pvNote)->pszPhysicalPath,
"C:\\InetPub\\cbroot\\%s",
phyfile);
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
BOOL WINAPI TerminateFilter(DWORD dwFlags)
{
return TRUE;
}
二、對訪問內容進行統計分析
通常我們在需要計數的頁面內放一個計數器,或者使用ASP文件來實現計數功能。
這種方法不能適用于如README.TXT等其他非HTML格式的文件。如果使用IIS的日志功
能又太占用空間而不方便。作者通過定制URL映射信息處理來跟蹤感興趣的幾個文件
的計數統計,將結果記錄在一個文件中。
下面是它的源程序。
fcount.def:
LIBRARY fcount
EXPORTS GetFilterVersion
HttpFilterProc
TerminateFilter
fcount.c:
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <httpfilt.h>
#define logfile "C:\\InetPub\\fcount.log"
#define pages 5
char* urls[] = {
"/default.htm",
"/banner.gif",
"/product/readme.txt",
"/product/product1.htm",
"/product/product2.htm"
};
int counts[pages];
BOOL WINAPI GetFilterVersion(HTTP_FILTER_VERSION *pVer)
{
int i;
pVer->dwFilterVersion = HTTP_FILTER_REVISION;
strcpy(pVer->lpszFilterDesc, "fcount");
pVer->dwFlags = SF_NOTIFY_URL_MAP; /* 過濾的內容 */
for (i=0; i<pages; i++)
{
/* 從文件讀入初始計數值 */
counts[i] = GetPrivateProfileInt("VisitCounter",
urls[i],
0,
logfile);
}
return TRUE;
}
DWORD WINAPI HttpFilterProc(HTTP_FILTER_CONTEXT *pfc,
DWORD noteType,
VOID *pvNote)
{
int i;
char lurl[512];
char buf[16];
strcpy(lurl, ((PHTTP_FILTER_URL_MAP)pvNote)->pszURL);
_strlwr(lurl);
for (i=0; i<pages; i++)
{
if (strcmp(lurl, urls[i])==0)
{
counts[i] ++; /* 計數值增加 */
if (counts[i]%10==0)
{
/* 當計數值滿10時記入文件,以免系統突然死掉時數據全部丟失 */
_itoa(counts[i], buf, 10);
WritePrivateProfileString("VisitCounter",
urls[i],
buf,
logfile);
}
break;
}
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
BOOL WINAPI TerminateFilter(DWORD dwFlags)
{
int i;
char buf[16];
for (i=0; i<pages; i++)
{
/* 系統停止時將計數值寫入文件 */
_itoa(counts[i], buf, 10);
WritePrivateProfileString("VisitCounter",
urls[i],
buf,
logfile);
}
return TRUE;
}
以上二個例子作者使用VC 6.0編譯,在WINNT 4.0 + SP3 和 IIS 3.0上調試通過。
原文轉自:http://www.kjueaiud.com