IHttpHandler的妙用(2):防盗链!我的资源只有我的用户才能下载
生活随笔
收集整理的這篇文章主要介紹了
IHttpHandler的妙用(2):防盗链!我的资源只有我的用户才能下载
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?
昨天粗略講了一下IHttpHandler接口的作用和動(dòng)態(tài)給圖片添加水印的處理,如果對(duì)這些不太清除的朋友,建議看看這篇《IHttpHandler的妙用(1):給圖片添加水印》:http://blog.csdn.net/zhoufoxcn/archive/2008/01/10/2033530.aspx 昨天也提到了IHttpHandler接口主要有一個(gè)IsReusable屬性和一個(gè)Proce***equest方法,利用這個(gè)方法我們可以處理很多事情的,昨天我們利用了這個(gè)方法給圖片動(dòng)態(tài)添加了水印,今天我再來(lái)展示另一種用法。 大家查看一個(gè)msdn,可以看到它的聲明如下:Visual?Basic(聲明)?
Sub?Proce***equest?(?_
????context?As?HttpContext?_
)
?
Visual?Basic(用法)?
Dim?instance?As?IHttpHandler
Dim?context?As?HttpContext
instance.Proce***equest(context)
?
C#?
void?Proce***equest?(
????HttpContext?context
) 注意這個(gè)HttpContext對(duì)象,它提供對(duì)用于為 HTTP 請(qǐng)求提供服務(wù)的內(nèi)部服務(wù)器對(duì)象(如 Request、Response、Session 和 Server)的引用。? 有了它我們就方便多了,因?yàn)槲覀兊南螺d資源一般都會(huì)有一個(gè)下載介紹(假設(shè)為details.aspx?id=***),用戶查看介紹之后,如果愿意下載,就會(huì)點(diǎn)擊下載鏈接,這個(gè)鏈接也是一個(gè)頁(yè)面(假設(shè)為download.aspx?id=***),我們就可以得出結(jié)論,只要是用戶通過(guò)我們的網(wǎng)站下載這些資源,那么在下載資源之前訪問(wèn)那個(gè)頁(yè)面(簡(jiǎn)稱前導(dǎo)頁(yè),下同)一定是details.aspx,因此我們就可以得出結(jié)論只要是下載之前的前導(dǎo)頁(yè)不是details.aspx這個(gè)頁(yè)面,那個(gè)這個(gè)下載請(qǐng)求一定是別的網(wǎng)站盜鏈(其實(shí)還可以放寬一點(diǎn),在下載之前的前導(dǎo)頁(yè)一定是本站的頁(yè)面,也還可以要求更緊一點(diǎn),下載之前訪問(wèn)的頁(yè)面的id值一定要與下載的id值一致,這就看大家的實(shí)際要求了)! 有了這個(gè)推論之后,我們就可以動(dòng)手寫代碼了:
using?System;
using?System.IO;
using?System.Web;
///?<summary>
///?說(shuō)明:DownloadHandler是一個(gè)防盜鏈的類,它可以防止本站資源被別的網(wǎng)站盜用
///?作者:周公
///?日期:2008-1-11
///?首發(fā)地址:http://blog.csdn.net/zhoufoxcn
///?</summary>
public?class?DownloadHandler:IHttpHandler
{
????public?DownloadHandler()
????{
????????//
????????//?TODO:?在此處添加構(gòu)造函數(shù)邏輯
????????//
????}
????#region?IHttpHandler?成員
????///?<summary>
????///?指示IHttpHandler?實(shí)例是否可再次使用
????///?</summary>
????public?bool?IsReusable
????{
????????get?{?return?true;?}
????}
????///?<summary>
????///?處理請(qǐng)求的方法
????///?</summary>
????///?<param?name="context">它提供對(duì)用于為?HTTP?請(qǐng)求提供服務(wù)的內(nèi)部服務(wù)器對(duì)象(如?Request、Response、Session?和?Server)的引用。</param>
????public?void?Proce***equest(HttpContext?context)
????{
????????Uri?referrerUri?=?context.Request.UrlReferrer;//獲取下載之前訪問(wèn)的那個(gè)頁(yè)面的uri
????????Uri?currentUri?=?context.Request.Url;
????????if?(referrerUri?==?null)//沒(méi)有前導(dǎo)頁(yè),直接訪問(wèn)下載頁(yè)
????????{
????????????//輸出提示,可以根據(jù)自身要求完善此處代碼
????????????context.Response.Write("請(qǐng)不要盜鏈本站資源,請(qǐng)從首頁(yè)訪問(wèn)。<a?href='index.aspx'>首頁(yè)</a>");
????????????return;
????????}
????????#region?判斷前導(dǎo)頁(yè)是否位于本站可以用此段代碼
????????//if?(referrerUri.Host?==?currentUri.Host)//前導(dǎo)頁(yè)和當(dāng)前請(qǐng)求頁(yè)位于同一個(gè)主機(jī)
????????//{
????????//????//用戶是通過(guò)正常路徑訪問(wèn)的,向用戶提供下載文件
????????//????//實(shí)際情況是根據(jù)id從數(shù)據(jù)庫(kù)找到文件的物理路徑,然后輸出
????????//????//為了簡(jiǎn)單代碼,僅僅演示流程,這里我直接輸出了文件
????????//????//周公注。2008-1-11
????????//????//獲取請(qǐng)求的物理文件路徑
????????//????WriteFile(context);
????????//}
????????//else
????????//{
????????//????//輸出提示,可以根據(jù)自身要求完善此處代碼
????????//????context.Response.Write("請(qǐng)不要盜鏈本站資源,請(qǐng)從首頁(yè)訪問(wèn)。<a?href='index.aspx'>首頁(yè)</a>");
????????//}
????????#endregion
????????#region?判斷前導(dǎo)頁(yè)是否是我們的介紹頁(yè)面
????????string?referrerPage?=?referrerUri.LocalPath.Substring(referrerUri.LocalPath.LastIndexOf('/')+1);
????????if?(referrerPage?==?"Details.aspx")//如果前導(dǎo)頁(yè)是我們的介紹頁(yè)面
????????{
????????????//用戶是通過(guò)正常路徑訪問(wèn)的,向用戶提供下載文件
????????????//實(shí)際情況是根據(jù)id從數(shù)據(jù)庫(kù)找到文件的物理路徑,然后輸出
????????????//為了簡(jiǎn)單代碼,僅僅演示流程,這里我直接輸出了文件
????????????//周公注。2008-1-11
????????????//獲取請(qǐng)求的物理文件路徑
????????????WriteFile(context);
????????}
????????else
????????{
????????????//輸出提示,可以根據(jù)自身要求完善此處代碼
????????????context.Response.Write("請(qǐng)不要盜鏈本站資源,請(qǐng)從首頁(yè)訪問(wèn)。<a?href='index.aspx'>首頁(yè)</a>");
????????}
????????#endregion
????}
????private?void?WriteFile(HttpContext?context)
????{
????????//用戶是通過(guò)正常路徑訪問(wèn)的,向用戶提供下載文件
????????//實(shí)際情況是根據(jù)id從數(shù)據(jù)庫(kù)找到文件的物理路徑,然后輸出
????????//為了簡(jiǎn)單代碼,僅僅演示流程,這里我直接輸出了文件
????????//周公注。2008-1-11
????????//獲取請(qǐng)求的物理文件路徑
????????string?path?=?context.Request.PhysicalPath;
????????//注意這里rar文件的ContentType是application/octet-stream
????????//不同格式文件的contentType有可能不同
????????context.Response.ContentType?=?"application/octet-stream";
????????context.Response.WriteFile(path);
????}
????#endregion
} 對(duì)web.config的配置:
<?xml?version="1.0"?>
<!--?
????注意:?除了手動(dòng)編輯此文件以外,您還可以使用?
????Web?管理工具來(lái)配置應(yīng)用程序的設(shè)置??梢允褂?Visual?Studio?中的
?????“網(wǎng)站”->“Asp.Net?配置”選項(xiàng)。
????設(shè)置和注釋的完整列表在?
????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>
????????<!--?
????????????設(shè)置?compilation?debug="true"?將調(diào)試符號(hào)插入
????????????已編譯的頁(yè)面中。但由于這會(huì)?
????????????影響性能,因此只在開(kāi)發(fā)過(guò)程中將此值?
????????????設(shè)置為?true。
????????-->
????????<compilation?debug="true"/>
????????<!--
????????????通過(guò)?<authentication>?節(jié)可以配置?ASP.NET?使用的?
????????????安全身份驗(yàn)證模式,
????????????以標(biāo)識(shí)傳入的用戶。?
????????-->
????????<authentication?mode="Windows"/>
????????<!--
????????????如果在執(zhí)行請(qǐng)求的過(guò)程中出現(xiàn)未處理的錯(cuò)誤,
????????????則通過(guò)?<customErrors>?節(jié)可以配置相應(yīng)的處理步驟。具體說(shuō)來(lái),
????????????開(kāi)發(fā)人員通過(guò)該節(jié)可以配置
????????????要顯示的?html?錯(cuò)誤頁(yè)
????????????以代替錯(cuò)誤堆棧跟蹤。
????????<customErrors?mode="RemoteOnly"?defaultRedirect="GenericErrorPage.htm">
????????????<error?statusCode="403"?redirect="NoAccess.htm"?/>
????????????<error?statusCode="404"?redirect="FileNotFound.htm"?/>
????????</customErrors>
????????-->
????????<httpHandlers>
??????<!--只處理UploadImages目錄下的jpg文件,別的目錄下的圖片不處理-->
????????????<add?path="UploadImages/*.jpg"?verb="*"?type="ImageHandler"/>
??????<!--所有的對(duì)zip、rar、iso文件的請(qǐng)求都由DownloadHandler處理-->
??????<add?path="*.zip"?verb="*"?type="DownloadHandler"/>
??????<add?path="*.rar"?verb="*"?type="DownloadHandler"/>
??????<add?path="*.iso"?verb="*"?type="DownloadHandler"/>
????????</httpHandlers>
????</system.web>
</configuration> 前導(dǎo)頁(yè)(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>無(wú)標(biāo)題頁(yè)</title>
</head>
<body>
????<form?id="form1"?runat="server">
????<div>
????<a?href="Download.aspx?id=1">下載</a>
????</div>
????</form>
</body>
</html> 下載頁(yè)沒(méi)有什么html代碼,主要是后臺(tái)代碼。下載頁(yè)后臺(tái)代碼(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
{
????protected?void?Page_Load(object?sender,?EventArgs?e)
????{
????????if?(!Page.IsPostBack)
????????{
????????????CheckUser();
????????????//實(shí)際情況是根據(jù)id從數(shù)據(jù)庫(kù)找到文件的物理路徑,然后輸出
????????????//為了簡(jiǎn)單代碼,僅僅演示流程,這里我直接輸出了文件
????????????//周公注。2008-1-11
????????????//首發(fā)地址:http://blog.csdn.net/zhoufoxcn
????????????Response.Redirect("download/demo.rar");//這里就會(huì)交給DownloadHanddler處理了
????????}
????}
????//檢查用戶登錄等信息
????private?void?CheckUser()
????{
????????//僅僅演示,具體代碼根據(jù)具體要求編寫
????????//比如用戶沒(méi)有登錄如何處理,用戶沒(méi)有下載權(quán)限如何處理等
????????return;
????}
} 正常流程截圖:
(一)先打開(kāi)介紹頁(yè)面:
(二)點(diǎn)擊下載鏈接進(jìn)入下載頁(yè)面:
此時(shí)出現(xiàn)文件保存對(duì)話框,情況正常。 再看盜鏈情況(非正常情況):
(一)打開(kāi)首頁(yè)(非前導(dǎo)頁(yè),跳過(guò)這一步也沒(méi)有關(guān)系)
(二)直接訪問(wèn)下載頁(yè)面或者直接訪問(wèn)下載文件的實(shí)際url地址:
此時(shí)出現(xiàn)了我們自定義的錯(cuò)誤提示,甚至地址欄上都出現(xiàn)了該文件的物理地址,可是就是沒(méi)有辦法下載,此時(shí)就算是利用迅雷等下載軟件,下載到的也是一個(gè)無(wú)效的文件,如圖:
這樣就達(dá)到我們的目地了,不是通過(guò)正常途徑來(lái)下載是沒(méi)有辦法下載到他需要的文件的。 順便說(shuō)一下,寫作本文時(shí)我是邊編寫代碼邊測(cè)試的(本博客原創(chuàng)的代碼都是如此,測(cè)試通過(guò)之后方才發(fā)表,所以一般不會(huì)有什么問(wèn)題,如果你學(xué)習(xí)的過(guò)程中發(fā)現(xiàn)有任何錯(cuò)誤,請(qǐng)仔細(xì)檢查你的代碼,因?yàn)楦魅吮镜丨h(huán)境不同,出錯(cuò)原因各異,恕本人不一一指出你代碼的錯(cuò)誤之處)。
轉(zhuǎn)載于:https://blog.51cto.com/zhoufoxcn/167036
總結(jié)
以上是生活随笔為你收集整理的IHttpHandler的妙用(2):防盗链!我的资源只有我的用户才能下载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【转】一位软件工程师的6年总结
- 下一篇: Windows 任务管理器进程详解