摘要:如何透過IHttpHandler讓某虛擬目錄中檔案(例如Test.txt)必須登入才可瀏覽
我們有時候會有這樣的需求,有些檔案也會希望使用者能夠經過登入驗證後,才能下載使用。然而對於.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,相關的程式內容如下:
Public Class CFileSafe
Implements IHttpHandler
Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
Get
End Get
End Property
Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
Dim FileName As String = context.Request.FilePath
Dim tmpS() As String
tmpS = FileName.Split(".")
Dim FileExten As String = LCase(tmpS(UBound(tmpS)))
Dim GetContentType As Boolean = False
Select Case FileExten
Case "txt"
context.Response.ContentType = "text/plain"
GetContentType = True
Case "doc"
context.Response.ContentType = "application/msword"
GetContentType = True
Case "xls"
context.Response.ContentType = "application/ms-excel"
GetContentType = True
Case "ppt"
context.Response.ContentType = "application/vnd.ms-powerpoint"
GetContentType = True
Case "pdf"
context.Response.ContentType = "application/pdf"
GetContentType = True
Case "zip"
context.Response.ContentType = "application/x-zip-compressed"
GetContentType = True
Case "gif"
context.Response.ContentType = "image/gif"
GetContentType = True
Case "tif"
context.Response.ContentType = "image/tiff"
GetContentType = True
Case "jpg"
context.Response.ContentType = "image/jpeg"
GetContentType = True
End Select
If GetContentType Then
context.Response.TransmitFile(context.Request.FilePath)
'context.Response.Write(FileExten)
Else
'context.Response.Write(FileExten)
context.Response.Write("未設定檔案格式【" & FileExten & "】!!")
End If
End Sub
End Class
接著要針對此資料夾(Files)增加一個Web.config來註冊IHttpHandler,順便指定此資料夾不允許未登入使用者存取
<?xml version="1.0" encoding="utf-8"?>
<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路徑複製下來,等一下用相同的檔案來處理我們要處理的副檔名
接著把其他的副檔名用相同的方式設定,這個部份的畫面就省略了。
經過以上的設定後,再來測試看看就會發現,當瀏覽Files下的Test.txt的時候,系統會自動導向到Login.aspx要求登入,登入完成後,自動再導回Test.txt的內容進行瀏覽。接著測試zip也一樣,在未登入的狀況下,會要求使用者進行登入,登入完成後,就會出現下載儲存的對話方塊。
以下是簽名:
- 歡迎轉貼本站的文章,不過請在貼文主旨上加上【轉貼】,並在文章中附上本篇的超連結與站名【topcat姍舞之間的極度凝聚】,感恩大家的配合。
- 小喵大部分的文章會以小喵熟悉的語言VB.NET撰寫,如果您需要C#的Code,也許您可以試著用線上的工具進行轉換,這裡提供幾個參考
Microsoft MVP Visual Studio and Development Technologies (2005~2019/6) | topcat Blog:http://www.dotblogs.com.tw/topcat |