### 防止盗链下载

盗链的含义是指内容不在自己服务器上，而通过技术手段，绕过别人的授权，直接在自己的页面上向最终用户提供此内容。盗链会导致被盗链站的直接经济损失、服务器外来压力以及盗链网站非正当手段获得其他利益（包括网友信任度以及广告投资等）。

本程序实现的是在网站上下载 ASP.NET 程序开发范例宝典（修定版）的“源程序下载试读”时，通过相应的技术手段防止其他未授权或非法网站通过盗链方法下载该资源。运行结果如图 1 所示。

图 1 防止盗链下载

#### 关键技术

本程序主要是通过在配置文件中配置下载方式、盗链功能是否开启及盗链默认转向的页面地址来防止下载文件时通过盗链方法非法的盗取该资源。

先来看一下 HTTP 文件的两种主要下载方式。

l URL 方式

URL 方式直接下载，优点是占用服务器资源少，速度快；缺点是不能准确计量下载次数，无法防止盗链，保存在数据库中的文件无法下载，常见格式的文件如.html 直接在浏览器中打开，不能直接下载。

l 二进制数据流方式

二进制数据流输出方式，优点是准确计量下载次数，能防盗链，所有文件格式都能直接下载而不是打开、保存在数据库中等非文件数据能以文件方式下载等；缺点是占用服务器资源多。

配置文件 Web.config 中的相应代码如下。

<appSettings>

<add key="Down" value="false"/>

<!--是否直接下载-->

<add key="Valid" value="false"/>

<!--是否允许盗链-->

<add key="Refers" value="localhost,mingrisoft.com"/>

<!--多个允许的访问来源用半角的","分割-->

<add key="DefaultRedirect" value="Error.htm"/>

<!--默认转向的页面-->

</appSettings>

#### 实现步骤

下面介绍“防止盗链下载”实例的实现步骤。

（1）新建一个网站，默认主页为 Default.aspx。

（2）在页面 Default.aspx 中添加一个个页面链接地址，用于导向下载的链接页面，编写的 HTML 代码如下。

<a href='<%="GetFile.aspx?FileName=" + Server.UrlEncode("测试.rar") %>'>源程序下载试读<span style="font-size: 11pt"></span></a>

（3）编写文件下载页面 GetFile.aspx 的后台程序代码。

在 Page_Load 事件中编写如下代码，主要用来判断配置文件是否直接下载，如果设置为防止盗链，判断访问来源是否合法，并时实更新下载次数。

protected void Page_Load(object sender, EventArgs e)

{

if (Request.QueryString["FileName"] == null)

{

InvalidRedirect();

}

string fileName = Request.QueryString["FileName"];

if (fileName == string.Empty)

{

InvalidRedirect();

}

//判断配置文件是否直接下载

string downDirect = ConfigurationManager.AppSettings["Down"].ToLower();

if (downDirect == "true")

{

UpdateHits(fileName);//更新下载次数

Response.Redirect("Upload/" + fileName);

return;

}

string path = Server.MapPath(Request.ApplicationPath + "/Upload/" + fileName);

string referrer = string.Empty;

if (Request.UrlReferrer != null)

{

referrer = Request.UrlReferrer.ToString().ToLower();

}

string d = ConfigurationManager.AppSettings["Valid"].ToLower();

string[] domainName = ConfigurationManager.AppSettings["Refers"].ToLower().Split(new char[] { ',' });

// 如果设置为防止盗链，判断访问来源是否合法

if (d == "false")

{

foreach (string s in domainName)

{

if (referrer.IndexOf(s.ToLower()) > 0)

{

UpdateHits(fileName);//更新下载次数

ResponseFile(path);

return;

}

}

InvalidRedirect();

}

else

{

ResponseFile(path);

}

}