您的位置:首页 > 理论基础 > 计算机网络

IHttpHandler的用法:资源下载,防盗链!

2012-02-28 18:35 393 查看
大家查看一个msdn,可以看到它的声明如下:

Visual Basic(声明)

Sub ProcessRequest ( _

context As HttpContext _

)

Visual Basic(用法)

Dim instance As IHttpHandler

Dim context As HttpContext

instance.ProcessRequest(context)

C#

void ProcessRequest (

HttpContext context

)

注意这个HttpContext对象,它提供对用于为 HTTP 请求提供服务的内部服务器对象(如 Request、Response、Session 和 Server)的引用。

有了它我们就方便多了,因为我们的下载资源一般都会有一个下载介绍(假设为details.aspx?id=***),用户查看介绍之后,如果愿意下载,就会点击下载链接,这个链接也是一个页面(假设为download.aspx?id=***),我们就可以得出结论,只要是用户通过我们的网站下载这些资源,那么在下载资源之前访问那个页面(简称前导页,下同)一定是details.aspx,因此我们就可以得出结论只要是下载之前的前导页不是details.aspx这个页面,那个这个下载请求一定是别的网站盗链(其实还可以放宽一点,在下载之前的前导页一定是本站的页面,也还可以要求更紧一点,下载之前访问的页面的id值一定要与下载的id值一致,这就看大家的实际要求了)!

有了这个推论之后,我们就可以动手写代码了:

using System;

using System.IO;

using System.Web;

/// <summary>

/// 说明:DownloadHandler是一个防盗链的类,它可以防止本站资源被别的网站盗用

/// 作者:周公

/// 日期:2008-1-11

/// 首发地址:http://blog.csdn.net/zhoufoxcn

/// </summary>

public
class DownloadHandler:IHttpHandler

{

public DownloadHandler()

{

//

// TODO: 在此处添加构造函数逻辑

//

}

#region IHttpHandler 成员

///
<summary>

/// 指示IHttpHandler 实例是否可再次使用

///
</summary>

publicbool IsReusable

{

get {returntrue; }

}

///
<summary>

/// 处理请求的方法

///
</summary>

///
<param name="context">它提供对用于为 HTTP 请求提供服务的内部服务器对象(如 Request、Response、Session 和 Server)的引用。</param>

publicvoid ProcessRequest(HttpContext context)

{

Uri referrerUri = context.Request.UrlReferrer;//获取下载之前访问的那个页面的uri

Uri currentUri = context.Request.Url;

if (referrerUri==null)//没有前导页,直接访问下载页

{

//输出提示,可以根据自身要求完善此处代码

context.Response.Write("请不要盗链本站资源,请从首页访问。<a href='index.aspx'>首页</a>");

return;

}

#region 判断前导页是否位于本站可以用此段代码

//if (referrerUri.Host == currentUri.Host)//前导页和当前请求页位于同一个主机

//{

//
//用户是通过正常路径访问的,向用户提供下载文件

//
//实际情况是根据id从数据库找到文件的物理路径,然后输出

//
//为了简单代码,仅仅演示流程,这里我直接输出了文件

//
//周公注。2008-1-11

//
//获取请求的物理文件路径

// WriteFile(context);

//}

//else

//{

//
//输出提示,可以根据自身要求完善此处代码

// context.Response.Write("请不要盗链本站资源,请从首页访问。<a href='index.aspx'>首页</a>");

//}

#endregion

#region 判断前导页是否是我们的介绍页面

string referrerPage= referrerUri.LocalPath.Substring(referrerUri.LocalPath.LastIndexOf('/')+1);

if (referrerPage=="Details.aspx")//如果前导页是我们的介绍页面

{

//用户是通过正常路径访问的,向用户提供下载文件

//实际情况是根据id从数据库找到文件的物理路径,然后输出

//为了简单代码,仅仅演示流程,这里我直接输出了文件

//周公注。2008-1-11

//获取请求的物理文件路径

WriteFile(context);

}

else

{

//输出提示,可以根据自身要求完善此处代码

context.Response.Write("请不要盗链本站资源,请从首页访问。<a href='index.aspx'>首页</a>");

}

#endregion

}

private
void WriteFile(HttpContext context)

{

//用户是通过正常路径访问的,向用户提供下载文件

//实际情况是根据id从数据库找到文件的物理路径,然后输出

//为了简单代码,仅仅演示流程,这里我直接输出了文件

//周公注。2008-1-11

//获取请求的物理文件路径

string path= context.Request.PhysicalPath;

//注意这里rar文件的ContentType是application/octet-stream

//不同格式文件的contentType有可能不同

context.Response.ContentType ="application/octet-stream";

context.Response.WriteFile(path);

}

#endregion

}

对web.config的配置:

<?xml version="1.0"?>

<!--

注意: 除了手动编辑此文件以外,您还可以使用

Web 管理工具来配置应用程序的设置。可以使用 Visual Studio 中的

“网站”->“Asp.Net 配置”选项。

设置和注释的完整列表在

machine.config.comments 中,该文件通常位于

WindowsMicrosoft.NetFrameworkv2.xConfig 中

-->

<configuration>

<appSettings>

<!--添加到图片上的水印文字-->

<add
key="WaterMark" value="http://blog.csdn.net/zhoufoxcn"/>

<!--水印文字的字体大小-->

<add
key="Font-Size" value="72"/>

</appSettings>

<connectionStrings/>

<system.web>

<!--

设置 compilation debug="true" 将调试符号插入

已编译的页面中。但由于这会

影响性能,因此只在开发过程中将此值

设置为 true。

-->

<compilationdebug="true"/>

<!--

通过 <authentication> 节可以配置 ASP.NET 使用的

安全身份验证模式,

以标识传入的用户。

-->

<authenticationmode="Windows"/>

<!--

如果在执行请求的过程中出现未处理的错误,

则通过 <customErrors> 节可以配置相应的处理步骤。具体说来,

开发人员通过该节可以配置

要显示的 html 错误页

以代替错误堆栈跟踪。

<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">

<error statusCode="403" redirect="NoAccess.htm" />

<error statusCode="404" redirect="FileNotFound.htm" />

</customErrors>

-->

<httpHandlers>

<!--只处理UploadImages目录下的jpg文件,别的目录下的图片不处理-->

<addpath="UploadImages/*.jpg" verb="*"
type="ImageHandler"/>

<!--所有的对zip、rar、iso文件的请求都由DownloadHandler处理-->

<add
path="*.zip" verb="*" type="DownloadHandler"/>

<add
path="*.rar" verb="*" type="DownloadHandler"/>

<add
path="*.iso" verb="*" type="DownloadHandler"/>

</httpHandlers>

</system.web>

</configuration>

前导页(Details.aspx):

<%@ Page Language="C#"
AutoEventWireup="true"
CodeFile="Details.aspx.cs"
Inherits="Details"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title>无标题页</title>

</head>

<body>

<form
id="form1" runat="server">

<div>

<a href="Download.aspx?id=1">下载</a>

</div>

</form>

</body>

</html>

下载页没有什么html代码,主要是后台代码。下载页后台代码(Download.aspx.cs):

using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

public
partial class Download : System.Web.UI.Page

{

protectedvoid Page_Load(object sender, EventArgs
e)

{

if (!Page.IsPostBack)

{

CheckUser();

//实际情况是根据id从数据库找到文件的物理路径,然后输出

//为了简单代码,仅仅演示流程,这里我直接输出了文件

//周公注。2008-1-11

//首发地址:http://blog.csdn.net/zhoufoxcn

Response.Redirect("download/demo.rar");//这里就会交给DownloadHanddler处理了

}

}

//检查用户登录等信息

privatevoid CheckUser()

{

//仅仅演示,具体代码根据具体要求编写

//比如用户没有登录如何处理,用户没有下载权限如何处理等

return;

}

}

正常流程截图:

(一)先打开介绍页面:



(二)点击下载链接进入下载页面:



此时出现文件保存对话框,情况正常。

再看盗链情况(非正常情况):

(一)打开首页(非前导页,跳过这一步也没有关系)

(二)直接访问下载页面或者直接访问下载文件的实际url地址:



此时出现了我们自定义的错误提示,甚至地址栏上都出现了该文件的物理地址,可是就是没有办法下载,此时就算是利用迅雷等下载软件,下载到的也是一个无效的文件,如图:



这样就达到我们的目地了,不是通过正常途径来下载是没有办法下载到他需要的文件的。

顺便说一下,写作本文时我是边编写代码边测试的(本博客原创的代码都是如此,测试通过之后方才发表,所以一般不会有什么问题,如果你学习的过程中发现有任何错误,请仔细检查你的代码,因为各人本地环境不同,出错原因各异,恕本人不一一指出你代码的错误之处)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: