如何透過IHttpHandler讓某虛擬目錄中檔案(例如Test.txt)必須登入才可瀏覽(或下載)
轉載 http://www.dotblogs.com.tw/topcat/archive/2008/03/06/1255.aspx
我們有時候會有這樣的需求,有些檔案也會希望使用者能夠經過登入驗證後,才能下載使用。然而對於.NET的驗證機制來說,他所保護的是aspx等asp.net的相關檔案,如果您的檔案是【txt文字檔】、【zip壓縮檔】、【doc Word檔】等,這些的檔案只要知道超連結,就可以直接下載。
那麼有沒有辦法讓這些的檔案也能夠跟aspx一樣,當瀏覽的時候,就檢查看是否有登入系統,如果未登入,就直接倒向到使用者登入畫面,當登入完成後,再進行該檔案的瀏覽或下載。
運作原理
我們知道在aspx的檔案在ASP.NET的驗證機制下,如果輸入ABC.aspx,系統會自動導向到我們指定的登入畫面(例如:Login.aspx),當登入驗證完成後,會再次導向回剛剛想要瀏覽的網頁ABC.aspx。而這些的機制,都是透過.NET Framework的ISAPI 【aspnet_isapi.dll】來處理的。因此我們希望我們指定的副檔名也能夠透過【aspnet_isapi.dll】的處理,做出相同的動作。因此要處理三件事情。
- 撰寫IHttpHandler處理這些檔案類型
- 設定Web.Config來註冊IHttpHandler,並且設定該資料夾Deny Users="?"
- 在IIS中註冊這些副檔名由【aspnet_isapi.dll】處理(這樣才能啟動IHttpHandler)
首先要在自己的系統上建立.NET的驗證機制。
接著,在自己的ASP.NET專案中建立一個資料夾(Files),希望未來存放在此資料夾中的指定檔案格式需要驗證。
再專案中新增一個類別(Class),命名為CFileSafe.vb,Imports命名空間System.Web
接著在Class中Implements IHttpHandler,VS自動會產生IsReusable的Property與ProcessRequest的Sub,接著撰寫處理Request的內容,判斷傳入的副檔名,依據不同的副檔名,指定不同的Response.ContentType,相關的程式內容如下:
- using System;
- using System.Data;
- using System.Configuration;
- 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;
- ///
- /// verifyFire 的摘要描述
- ///
- public class verifyFire : IHttpHandler
- {
- public verifyFire()
- {
- //
- // TODO: 在此加入建構函式的程式碼
- //
- }
- bool IHttpHandler.IsReusable
- {
- get { throw new Exception("The method or operation is not implemented."); }
- }
- public void ProcessRequest(HttpContext context)
- {
- string FileName = context.Request.FilePath;
- string[] tmpS = FileName.Split(new Char[] { '.' });
- string FileExten = tmpS[tmpS.Rank].ToLower();
- bool GetContentType = false;
- switch (FileExten)
- {
- case "txt":
- context.Response.ContentType = "text/plain";
- GetContentType = true;
- break;
- case "doc":
- context.Response.ContentType = "application/msword";
- GetContentType = true;
- break;
- case "xls":
- context.Response.ContentType = "application/ms-excel";
- GetContentType = true;
- break;
- case "ppt":
- context.Response.ContentType = "application/vnd.ms-powerpoint";
- GetContentType = true;
- break;
- case "pdf":
- context.Response.ContentType = "application/pdf";
- GetContentType = true;
- break;
- case "zip":
- context.Response.ContentType = "application/x-zip-compressed";
- GetContentType = true;
- break;
- case "gif":
- context.Response.ContentType = "image/gif";
- GetContentType = true;
- break;
- case "tif":
- context.Response.ContentType = "image/tiff";
- GetContentType = true;
- break;
- case "jpg":
- context.Response.ContentType = "image/jpeg";
- GetContentType = true;
- break;
- }
- if (GetContentType)
- {
- context.Response.TransmitFile(context.Request.FilePath);
- }
- //context.Response.Write(FileExten)
- else
- {
- //context.Response.Write(FileExten)
- context.Response.Write("未設定檔案格式【" + FileExten + "】!!");
- }
- }
- }




























































接著要針對此資料夾(Files)增加一個Web.config來註冊IHttpHandler,順便指定此資料夾不允許未登入使用者存取
<!-- 注意: 除了手動編輯這個檔案以外,您也可以使用 Web 管理工具
設定您的應用程式設定值。請使用 Visual Studio 中的
[網站] -> [ASP.NET 組態] 選項。
如需完整的設定與註解清單,請參考 machine.config.comments (通常
位於 \Windows\Microsoft.NET\Framework\v2.0.xxxxx\Config)
-->
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<httpHandlers>
<add verb="*" path="*.*" type="CFileSafe"/>
</httpHandlers>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</configuration>
程式的部分就到此為止,接著就可以放些測試的檔案到此資料夾中,並且拉出超連結到Login.aspx中,方便測試登入的驗證。
此時執行Login.aspx,點選超鏈結到Test.txt,卻發現還是沒有要求登入就直接顯示?原因是我們還少了最後的一個步驟→設定這些檔案格式給ISAPI處理
開啟IIS,瀏覽到我們ASP.NET應用程式中的Files資料夾,點選滑鼠右鍵→內容。
當我們要設定ISAPI的時候發現,由於他不是個應用程式,所以無法針對Files設定ISAPI
此時我們可以先暫時把該資料夾建立為應用程式,讓他可以設定,等設定完成後再把應用程式移除即可。
將處理aspx的aspnet_isapi.dll路徑複製下來,等一下用相同的檔案來處理我們要處理的副檔名
接著新增一個副檔名的處理,我們舉txt來當作範例
接著把其他的副檔名用相同的方式設定,這個部份的畫面就省略了。
經過以上的設定後,再來測試看看就會發現,當瀏覽Files下的Test.txt的時候,系統會自動導向到Login.aspx要求登入,登入完成後,自動再導回Test.txt的內容進行瀏覽。接著測試zip也一樣,在未登入的狀況下,會要求使用者進行登入,登入完成後,就會出現下載儲存的對話方塊。