在ASP.NET環境中,如何防止圖片防止被盜連

在ASP.NET環境中,如何防止圖片防止被盜連

        當辛辛苦苦經營的網站或部落格,不論是在撰寫技術文章,或者是長期經營知識分享的文章以及各種具有廣大吸引力的圖片資源,

經營一段時間後,會發現流量逐漸變大,但是實際網站訪問量卻沒有哪麼大,而且也常在GOOGLE搜尋引擎搜尋到自己的製作或上傳

在自己專屬的網頁圖片,竟然被盜用,看到別人直接盜連自己的圖片,想必一定很生氣,畢竟流量是浪費自己主機的資源,但網站訪

問量卻是盜用者坐享其成,所以此篇文章將是分享如何在ASP.NET以及IIS環境下,建構出防止圖片被盜連。

      正常情況下,Client 端向 Server端(IIS)提出一個request時,IIS會判斷該請求的路徑網址檔案的類型,而這類型就是根據副檔名

來加以辨別,進而委託可以相應的Module來處理,但此請求處理過程會根據IIS的版本有所差異,此列出圖一與圖二來展現其差異性

(圖一) IIS 6的請求處理過程機制

image

(圖二) IIS 7的請求處理過程機制

image

簡單的解釋分析IIS 6與 IIS 7之間的差異性,在IIS 6模式裡,將對於ASP.NET的處理都獨立出一個 Request Process Pipeline,

也就是當IIS發覺是由ASP.NET負責一個獨立的 Request Process Pipelie進行處理,處理後再返回給IIS。而在IIS 7模式裡,

它將原本的"Reuest Process"整合在一起,這樣一來不只可以減少原本需要兩條管線處理的成本,也擴展了系統的彈性與擴充性。    

       這裡要先把關鍵技術突破,在ASP.NET是透過Handler機制來處理防止圖片資源被盜連,一般瀏覽器向IIS伺服器提出請求
時,是根據副檔名來對應相關的處理模組,如 default.aspx (副檔名為.aspx ),當IIS SERVER收到此請求時,將知道不自己處理
,而是進而將他委託給後端的 ISAPI 擴充程序來處理ASP.NET Page的請求處理,而副檔名為.htm(html)或.txt 以及大部分的
圖片檔(.jpg、.gif、.png)都將由IIS直接進行處理請求,在將請求直接回應給瀏覽器客戶端,因而如果能夠在請求圖片資源時,
可以判斷請求的位址如不是授權的範圍將是盜連,將不給予存取,而ASP.NET實作Handler有兩種機制,一種是透過簡單的
”泛型處理常式”,另外一種就是透過實作一個繼承 IHttpHandler介面的Class,事實上泛型處理常式也是繼承自IHttpHandler,
只是它由.Net幫你做好一切的雛型,你不需要特別去設定web.config檔也不用去設定副檔名類型的對應關係,反之如果需要
更客製化的需求就須自己動手實作一個繼承 IHttpHandler介面的Class ,並設定Web.Config檔的對應關係。

        接下來實作篇,就教大家如何透過實作一個繼承 IHttpHandler介面的機制來防止圖片檔遭盜連

(實作篇)

1.首先在Visual Studio 的 Web網站裡,新增一個Web Page,並命名為image.aspx

image

2.從工具箱拖拉一個image控制項到 image.aspx頁面,並將image的來源指定一個圖片檔(jpg)。如下圖

image

瀏覽器預覽結果
image

接下來開始實作一個繼承IHttpHandler介面的Class

3.新增一個類別(class),檔名我們命名為 jpgProcessHandler.cs

image

(ToolTip)

當按下新增按鈕時,Visual Studio會提示要將檔案存放一個新增的App_Code,請按是….

4.在 jpgProcessHandler.cs程式碼頁面,我們需要繼承一個 IHttpHandler,因此請將程式實作為以下結果

   1: public class jpgProcessHandler :IHttpHandler
   2: {
   3:     public jpgProcessHandler()
   4:     {
   5:         //
   6:         // TODO: 在此加入建構函式的程式碼
   7:         //
   8:     }
   9:  
  10:     public bool IsReusable
  11:     {
  12:         get { throw new NotImplementedException(); }
  13:     }
  14:  
  15:     public void ProcessRequest(HttpContext context)
  16:     {
  17:         throw new NotImplementedException();
  18:     }
  19: }

這裡有兩個IHttpHandler介面的方法成員需要講解,分別為IsReusableProcessRequest ,IsReusalbe是傳回一個bool值,用意在指示是否重復使用這個class建立出來的instance,而ProcessRequest才是接下來防止盜連的程式碼核心所在,所以接下來我們在此方法實作下列程式碼

  1: public void ProcessRequest(HttpContext context)
  2:    {
  3:        //判斷請求圖片檔案的主機來源
  4:        if (context.Request.UrlReferrer.Host != "localhost")
  5:        {
  6:            //如果不是從本機提出的請求,將應於拒絕...
  7:            //可以在此處的localhost改為實際上線的IP
  8: 
  9:            //設定瀏覽器端得快取過期時間,此設定0即立即過期。
 10:            context.Response.Expires = 0;
 11:            //清除所有暫存快取
 12:            context.Response.Clear();
 13:            //設定MIME文件對應類型
 14:            context.Response.ContentType = "image/jpg";
 15:            //將自訂的盜連圖片出現在網頁裡,以警示非法存取

16: context.Response.WriteFile(context.Request.PhysicalApplicationPath

+ "images\\ErrorForThief.jpg");

 17:            //快取輸出至瀏覽器端
 18:            context.Response.End();
 19:        }
 20:        else
 21:        {
 22:            //設定瀏覽器端得快取過期時間,此設定0即立即過期。
 23:            context.Response.Expires = 0;
 24:            //清除所有暫存快取
 25:            context.Response.Clear();
 26:            //設定MIME文件對應類型
 27:            context.Response.ContentType = "image/jpg";
 28:            //將請求的實際圖片檔寫入buffer
 29:            context.Response.WriteFile(context.Request.PhysicalPath);
 30:            //快取輸出至瀏覽器端
 31:            context.Response.End();
 32: 
 33:        }
 34:    }
程式寫好了後,需要在WEB.CONFIG檔,宣告對應的Mapping Handler程式,如下所示:
   1: <httpHandlers>
   2:   <add verb="*" path="*.jpg" type="jpgProcessHandler, App_Code" />
   3: </httpHandlers>
   4: system.web>
 
當完成上述程式碼再去執行一次網頁,就會發現如果存取圖片的來源主機位址不是localhost
就會出現筆者自行製作的警示圖片,如下圖:
image
最後提醒,如果IIS的版本是7.0以上,就特別也要在web.config檔裡的<system.webServer>
和 </system.webServer>裡再重復宣告對應的Mapping Handler程式,如下:
image

如果根據上述做法,就能很有效率的阻擋不該存取的資源!