作者在 2008-12-25 13:14:34 发布以下内容
				//ISAPI Filter实现网站资源防盗链
//by redice 2008.12.25 redice@163.com
原理很简单,就一句话:检查HTTP请求报头中的Referer字段是否为服务器网站的主机头,如果不是则决绝该请求。
完整的代码如下:
//filter.cpp
#include <windows.h>
// 包含了ISAPI过滤器所需的定义和原型
#include <httpfilt.h>
#include <stdio.h>
// 过滤器描述信息
#define FILTER_DESCRIPTION "Isapi Filter v1.0"
//SF_NOTIFY_READ_RAW_DATA通知处理
/*DWORD HandleEvent_ReadRawData(HTTP_FILTER_CONTEXT *pfc,
							  HTTP_FILTER_RAW_DATA *pReadData);*/
//SF_NOTIFY_URL_MAP通知处理
DWORD HandleEvent_OnUrlMap(HTTP_FILTER_CONTEXT *pfc,
							  HTTP_FILTER_URL_MAP *pUrlData);
// 获取文件的后缀名并转换为小写
char * GetFileExtensionLCase(char * filepath,char * extension,DWORD  *dwSize);
// DLL入口
BOOL WINAPI DllMain(HINSTANCE hinstDll,DWORD dvReason,LPVOID lpv)
{
	OutputDebugString("DllMain\n");
	return TRUE;
}
//GetFilterVersion
BOOL WINAPI GetFilterVersion(HTTP_FILTER_VERSION *pVersion)
{
	//设置过滤器版本号
	pVersion->dwFilterVersion=HTTP_FILTER_REVISION;
	//设置过滤器描述信息
	strncpy(pVersion->lpszFilterDesc,FILTER_DESCRIPTION,SF_MAX_FILTER_DESC_LEN);
	// 注册感兴趣的通知,设置过滤器的优先级
	pVersion->dwFlags=(SF_NOTIFY_ORDER_HIGH|
		SF_NOTIFY_SECURE_PORT|    //Server在安全端口上收到一个客户连接
		SF_NOTIFY_NONSECURE_PORT| //Server在非安全端口上收到一个客户连接
		//SF_NOTIFY_READ_RAW_DATA | //Server从Client读取了数据
		SF_NOTIFY_URL_MAP);       //Server准备简化逻辑URL映射为实际路径
	return TRUE;
}
// HttpFilterProc
DWORD WINAPI HttpFilterProc(HTTP_FILTER_CONTEXT *pfc,
							DWORD dwNotificationType,VOID *pvData)
{
	DWORD dwRet=SF_STATUS_REQ_NEXT_NOTIFICATION;
	switch(dwNotificationType)
	{
	/*case SF_NOTIFY_READ_RAW_DATA:
		dwRet=HandleEvent_ReadRawData(pfc,
			(HTTP_FILTER_RAW_DATA *)pvData);
		break;*/
	case SF_NOTIFY_URL_MAP:
		dwRet=HandleEvent_OnUrlMap(pfc,
			(HTTP_FILTER_URL_MAP *)pvData);
     break;
	}
	return dwRet;
}
/*
//SF_NOTIFY_READ_RAW_DATA通知处理
DWORD HandleEvent_ReadRawData(HTTP_FILTER_CONTEXT *pfc,
							  HTTP_FILTER_RAW_DATA *pReadData)
{
	DWORD dwRet=SF_STATUS_REQ_NEXT_NOTIFICATION;
	return dwRet;
}
*/
//SF_NOTIFY_URL_MAP通知处理
DWORD HandleEvent_OnUrlMap(HTTP_FILTER_CONTEXT *pfc,
							  HTTP_FILTER_URL_MAP *pUrlData)
{
	DWORD dwRet=SF_STATUS_REQ_NEXT_NOTIFICATION;
	char fileext[10]={0}; //文件后缀名
	DWORD dwSize=0;
	// 获取文件的后缀名,并转换为小写
	dwSize=10;
	GetFileExtensionLCase(pUrlData->pszPhysicalPath,fileext, &dwSize);
	if(dwSize)
	{
		//如果文件后缀名为gif,jpg,png中的一种
		if(!strcmp(fileext,"gif") || !strcmp(fileext,"jpg") || !strcmp(fileext,"png") )
		{
			//检查HTTP报头中Referer
			char Referer[256]={0};
			char Host[256]={0};
			dwSize=256;
			pfc->GetServerVariable(pfc,"HTTP_REFERER",Referer,&dwSize);
			OutputDebugString(Referer);
			dwSize=256;
			if(pfc->GetServerVariable(pfc,"HTTP_HOST",Host,&dwSize));
			OutputDebugString(Host);
			if(!strstr(Referer,Host)) //如果Referer中不含有Host
			{
				//我们决绝这次请求,或者修改pUrlData->pszPhysicalPath的值
				pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,
					"403 Forbidden \r\n",0,(DWORD)NULL);
				return SF_STATUS_REQ_FINISHED;
			}
		}
	}
	return dwRet;
}
// 获取文件的后缀名并转换为小写
char * GetFileExtensionLCase(char * filepath,char * extension,DWORD  *dwSize)
{
	unsigned int i=0,j=0;
	for(;i<strlen(filepath);i++)
	{
		if(filepath[i]!='\\' && filepath[i]!='.')
		{
			if(j>*dwSize-2)
			{
				memset(extension,0,*dwSize);
				j=0;
			}
			extension[j++]=filepath[i];
		}
		else
		{
			memset(extension,0,*dwSize);
			j=0;
		}
	}
	*dwSize=j+1;
	return _strlwr(extension);
}
//Moudle.def
EXPORTS
GetFilterVersion
HttpFilterProc
DllMain
或给我发Email索取源码。。。
本博客于即日起(2009.2.26)停止更新,

