Segnala il sito a un amico |
|
|
Se hai trovato questa pagina interessante, scrivilo ad un amico, clicca qui |
|
|
NEW!! GiDiNet Web Directory |
|
|
GiDiNet Directory è una Web Directory divisa in più aree tematiche in cui potrete
trovare comodamente siti che trattano argomenti di vostro interesse, continua... |
|
|
Statistiche |
|
Oggi
21/11/2024
sei il visitatore n.
per un totale di
visitatori dal 23/04/2007
|
|
|
|
|
Hai un problema particolare? Non trovi quello che stai cercando? clicca qui!
Script anti-hotlinking - ASP.NET 2.0
Lo script pubblicato in questa pagina ha lo scopo di creare un sistema anti-hotlinking semi-automatico sfruttando le funzionalità del .NET Framework v2.0.
Il sistema sfrutta due caratteristiche tipiche di ASP.NET:
- Di default ASP.NET 2.0 blocca il download da browser dei file con estensione .exclude
- Tutte le richieste verso pagine aspx passano sempre attraverso gli http handler, anche se il file richiesto non esiste
Quindi sfruttando queste caratteristiche si può creare una semplice soluzione anti-hotlinking, che richiede minimi interventi sul sito, e soprattutto non richiede interventi di configurazione sul server web.
La protezione viene applicata richiamando dalla directory pubblica un file nella forma "nomefile.ext.aspx", il sistema restituisce il file "nomefile.ext.exclude" che viene prelevato dalla directory privata.
1. Installazione dello script
Per l'installazione dello script è sufficiente creare due file /App_Code/AntiLeechHandler.vb e /Web.config secondo quanto indicato di seguito
Se il file /Web.config fosse già presente sullo spazio web, basterà modificarlo inserendo quanto riportato in grassetto nelle sezioni indicate.
Scarica i sorgenti completi
Se avete ASP.NET 1.X potete trovare la versione modificata dello script su questa pagina.
Codice del file /App_Code/AntiLeechHandler.vb:
'Copyright (C) 2007 Daniele Iunco
'This program is free software; you can redistribute it and/or modify
'it under the terms of the GNU General Public License as published by
'the Free Software Foundation; either version 2 of the License, or
'(at your option) any later version.
'This program is distributed in the hope that it will be useful,
'but WITHOUT ANY WARRANTY; without even the implied warranty of
'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
'GNU General Public License for more details.
'You should have received a copy of the GNU General Public License along
'with this program; if not, write to the Free Software Foundation, Inc.,
'51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Imports System
Imports System.Configuration
Imports System.Web
Imports System.IO
Namespace GiDiNet
'AntiLeechHandler
'Author: Daniele Iunco
'Date: 6th May 2007
Public Class AntiLeechHandler
Implements IHttpHandler
Private Shared _Settings As AntiLeechSettings
Private Shared ReadOnly Property Settings() As AntiLeechSettings
Get
If _Settings Is Nothing Then _Settings = New AntiLeechSettings()
Return _Settings
End Get
End Property
Private Enum ReturnType
PageMissing = 0
ImageMissing = 1
PageNoLeech = 2
ImageNoLeech = 3
End Enum
Private Sub ProcessInvalidRequest(ByRef Context As HttpContext, ByVal myType As ReturnType)
'TODO: Qui si potrebbe sviluppare un sistema per registrare le richieste respinte
Select Case myType
Case ReturnType.PageMissing
Context.Response.Redirect(Settings.AntiLeechModule_MissingPageURL)
Case ReturnType.ImageMissing
Context.Response.Redirect(Settings.AntiLeechModule_MissingImageURL)
Case ReturnType.PageNoLeech
Context.Response.Redirect(Settings.AntiLeechModule_NoLeechPageURL)
Case ReturnType.ImageNoLeech
Context.Response.Redirect(Settings.AntiLeechModule_NoLeechImageURL)
End Select
End Sub
Public Sub ProcessRequest(ByVal Context As HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
Dim myRequestPath As String = Context.Request.Path.ToLower()
'Prelevo la configurazione della directory richiesta, se non la trovo restituisco la pagina di errore
Dim myDirectory As ProtectedDirectory = Settings.GetProtectedDirectory(myRequestPath)
If myDirectory Is Nothing Then
'Se non ho trovato una directory restituisco la pagina di errore
ProcessInvalidRequest(Context, ReturnType.PageMissing)
Exit Sub
End If
'Questo primo controllo serve per evitare di eseguire troppe verifiche inutili:
'Se l'estensione più corta è di 3 caratteri e aggiungo 7 caratteri, la lunghezza del percorso richiesto deve essere per forza maggiore di 10 caratteri (la richiesta è nella forma "/percorso/a.ext.aspx")
If myRequestPath.Length < myDirectory.PublicPath.Length + 10 Then
ProcessInvalidRequest(Context, ReturnType.PageMissing)
Exit Sub
End If
'Queste tre righe fanno una verifica davvero semplice sul referer, si potrebbero anche usare le espressioni regolari, fare attenzione a gestire i referer nulli
'Volendo posso verificare in modo più approfondito se il file "localPath" può essere davvero scaricato (es. verificando estensione, percorso, autorizzazioni, etc)
Dim myReferer As String = Context.Request.ServerVariables("HTTP_REFERER")
If myReferer Is Nothing Then myReferer = ""
Dim bIsValidReferer As Boolean = Settings.IsValidReferer(myReferer)
'Preparo la stringa col percorso reale
Dim newPath As String = myDirectory.PrivatePath & myRequestPath.Substring(myDirectory.PublicPath.Length)
newPath = newPath.Substring(0, newPath.LastIndexOf("."))
'Qui avviene l'impostazione del content type, se necessario aggiungere gli altri tipi di file
If newPath.Substring(newPath.LastIndexOf(".") + 1).ToLower = "gif" Then
If Not bIsValidReferer Then ProcessInvalidRequest(Context, ReturnType.ImageNoLeech) : Exit Sub
Context.Response.ContentType = "image/gif"
ElseIf newPath.Substring(newPath.LastIndexOf(".") + 1).ToLower = "zip" Then
If Not bIsValidReferer Then ProcessInvalidRequest(Context, ReturnType.PageNoLeech) : Exit Sub
Context.Response.ContentType = "application/x-zip-compressed"
ElseIf newPath.Substring(newPath.LastIndexOf(".") + 1).ToLower = "jpg" Then
If Not bIsValidReferer Then ProcessInvalidRequest(Context, ReturnType.ImageNoLeech) : Exit Sub
Context.Response.ContentType = "image/jpeg"
ElseIf newPath.Substring(newPath.LastIndexOf(".") + 1).ToLower = "png" Then
If Not bIsValidReferer Then ProcessInvalidRequest(Context, ReturnType.ImageNoLeech) : Exit Sub
Context.Response.ContentType = "image/png"
Else
If Not bIsValidReferer Then ProcessInvalidRequest(Context, ReturnType.PageNoLeech) : Exit Sub
End If
Dim localPath As String = Context.Server.MapPath(newPath) & ".exclude"
If Not File.Exists(localPath) Then ProcessInvalidRequest(Context, ReturnType.PageMissing) : Exit Sub
'Imposto il nome del file
Context.Response.AddHeader("Content-Disposition", "attachment; filename=" & newPath.Substring(newPath.LastIndexOf("/") + 1))
'Invio il file al browser, su ASP.NET 2.0 posso usare Response.TransmitFile per ridurre il carico di lavoro sul server, su ASP.NET 1.x dovrò usare Response.WriteFile
Context.Response.TransmitFile(localPath)
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
Get
Return True
End Get
End Property
End Class
Public Class ProtectedDirectory
Private _PublicPath As String
Public ReadOnly Property PublicPath() As String
Get
Return _PublicPath
End Get
End Property
Private _PrivatePath As String
Public ReadOnly Property PrivatePath() As String
Get
Return _PrivatePath
End Get
End Property
Public Sub New(ByVal PublicPath As String, ByVal PrivatePath As String)
_PublicPath = PublicPath
_PrivatePath = PrivatePath
End Sub
End Class
Public Class AntiLeechSettings
Public ReadOnly Property AllowedDomains() As String()
Get
Return _AllowedDomains
End Get
End Property
Public ReadOnly Property ProtectedDirectories() As ProtectedDirectory()
Get
Return _ProtectedDirectories
End Get
End Property
Public ReadOnly Property AntiLeechModule_NoLeechImageURL() As String
Get
Return _AntiLeechModule_NoLeechImageURL
End Get
End Property
Public ReadOnly Property AntiLeechModule_NoLeechPageURL() As String
Get
Return _AntiLeechModule_NoLeechPageURL
End Get
End Property
Public ReadOnly Property AntiLeechModule_MissingImageURL() As String
Get
Return _AntiLeechModule_MissingImageURL
End Get
End Property
Public ReadOnly Property AntiLeechModule_MissingPageURL() As String
Get
Return _AntiLeechModule_MissingPageURL
End Get
End Property
Private _AllowedDomains As String()
Private _ProtectedDirectories As ProtectedDirectory()
Private _AntiLeechModule_NoLeechImageURL As String
Private _AntiLeechModule_NoLeechPageURL As String
Private _AntiLeechModule_MissingImageURL As String
Private _AntiLeechModule_MissingPageURL As String
Public Sub New()
'Caricamento delle varie impostazioni dal file di configurazione
Dim myDomainNumberString As String = ConfigurationManager.AppSettings("AntiLeechModule_DomainNumber")
If IsNumeric(myDomainNumberString) Then
ReDim _AllowedDomains(myDomainNumberString - 1)
Else
ReDim _AllowedDomains(0)
End If
For i As Integer = 1 To _AllowedDomains.Length
Dim tmpItem As String
tmpItem = ConfigurationManager.AppSettings("AntiLeechModule_AllowedDomain_" & i)
If Not tmpItem Is Nothing AndAlso tmpItem.Length > 0 Then
_AllowedDomains(i - 1) = tmpItem.Trim.ToLower
Else
_AllowedDomains(i - 1) = ""
End If
Next
_AntiLeechModule_NoLeechImageURL = ConfigurationManager.AppSettings("AntiLeechModule_NoLeechImageURL")
If _AntiLeechModule_NoLeechImageURL Is Nothing Then _AntiLeechModule_NoLeechImageURL = "/"
_AntiLeechModule_NoLeechPageURL = ConfigurationManager.AppSettings("AntiLeechModule_NoLeechPageURL")
If _AntiLeechModule_NoLeechPageURL Is Nothing Then _AntiLeechModule_NoLeechPageURL = "/"
_AntiLeechModule_MissingImageURL = ConfigurationManager.AppSettings("AntiLeechModule_MissingImageURL")
If _AntiLeechModule_MissingImageURL Is Nothing Then _AntiLeechModule_MissingImageURL = "/"
_AntiLeechModule_MissingPageURL = ConfigurationManager.AppSettings("AntiLeechModule_MissingPageURL")
If _AntiLeechModule_MissingPageURL Is Nothing Then _AntiLeechModule_MissingPageURL = "/"
Dim myProtectedDirectoryNumberString As String = ConfigurationManager.AppSettings("AntiLeechModule_DirectoryNumber")
If IsNumeric(myProtectedDirectoryNumberString) Then
ReDim _ProtectedDirectories(myProtectedDirectoryNumberString - 1)
Else
ReDim _ProtectedDirectories(0)
End If
For i As Integer = 1 To _ProtectedDirectories.Length
Dim tmpItem1, tmpItem2 As String
tmpItem1 = ConfigurationManager.AppSettings("AntiLeechModule_DirectoryPublic_" & i)
tmpItem2 = ConfigurationManager.AppSettings("AntiLeechModule_DirectoryPrivate_" & i)
If Not tmpItem1 Is Nothing AndAlso tmpItem1.Length > 0 AndAlso Not tmpItem2 Is Nothing AndAlso tmpItem2.Length > 0 Then
_ProtectedDirectories(i - 1) = New ProtectedDirectory(tmpItem1, tmpItem2)
Else
_ProtectedDirectories(i - 1) = New ProtectedDirectory("/", "/")
End If
Next
End Sub
Public Function GetProtectedDirectory(ByVal RequestPath As String) As ProtectedDirectory
If RequestPath Is Nothing Then Return Nothing
'Verifico se la directory della richiesta è una sottodirectory di un percorso protetto, e in questo caso restituisco i parametri di configurazione
For i As Integer = 0 To ProtectedDirectories.Length - 1
If RequestPath.Substring(0, ProtectedDirectories(i).PublicPath.Length) = ProtectedDirectories(i).PublicPath Then Return ProtectedDirectories(i)
Next
Return Nothing
End Function
Public Function IsValidReferer(ByVal RefererString As String) As Boolean
If RefererString Is Nothing Then Return False
For i As Integer = 0 To AllowedDomains.Length - 1
RefererString = RefererString.ToLower
If RefererString.IndexOf(AllowedDomains(i)) >= 0 Then Return True
Next
Return False
End Function
End Class
End Namespace
Codice del file /Web.config:
Nota: Se sul server web è già presente un file web.config, modificare il file esistente inserendo le righe indicate in grassetto nelle rispettive sezioni (appSettings e httpHandlers)
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="AntiLeechModule_DomainNumber" value="3"></add>
<add key="AntiLeechModule_AllowedDomain_1" value="http://www.primodominio.com"></add>
<add key="AntiLeechModule_AllowedDomain_2" value="http://www.secondodominio.com"></add>
<add key="AntiLeechModule_AllowedDomain_3" value="http://www.terzodominio.com"></add>
<add key="AntiLeechModule_NoLeechImageURL" value="http://hostname.com/AlertImage.gif"></add>
<add key="AntiLeechModule_NoLeechPageURL" value="http://hostname.com/AlertPage.htm"></add>
<add key="AntiLeechModule_MissingImageURL" value="http://hostname.com/404.gif"></add>
<add key="AntiLeechModule_MissingPageURL" value="http://hostname.com/404.htm"></add>
<add key="AntiLeechModule_DirectoryNumber" value="2"></add>
<add key="AntiLeechModule_DirectoryPublic_1" value="/directory1/"></add>
<add key="AntiLeechModule_DirectoryPrivate_1" value="/directory1/secure/"></add>
<add key="AntiLeechModule_DirectoryPublic_2" value="/directory2/"></add>
<add key="AntiLeechModule_DirectoryPrivate_2" value="/directory2/secure/"></add>
</appSettings>
<system.web>
<httpHandlers>
<add verb="GET" path="*.zip.aspx" type="GiDiNet.AntiLeechHandler"></add>
<add verb="GET" path="*.jpg.aspx" type="GiDiNet.AntiLeechHandler"></add>
<add verb="GET" path="*.png.aspx" type="GiDiNet.AntiLeechHandler"></add>
<add verb="GET" path="*.gif.aspx" type="GiDiNet.AntiLeechHandler"></add>
</httpHandlers>
</system.web>
</configuration>
2. Configurazione e uso dello script
Per la configurazione è necessario modificare i parametri nel file /Web.config, seguendo le istruzioni riportate di seguito:
Parametri generali:
AntiLeechModule_NoLeechImageURL: Indicare l'indirizzo di un'immagine da visualizzare per le richieste respinte.
AntiLeechModule_NoLeechPageURL: Indicare l'indirizzo di una pagina web da visualizzare per le richieste respinte.
AntiLeechModule_MissingImageURL: Indicare l'indirizzo di un'immagine da visualizzare per le richieste di file non esistenti.
AntiLeechModule_MissingPageURL: Indicare l'indirizzo di una pagina web da visualizzare per le richieste di file non esistenti.
Selezione dei domini autorizzati ad effettuare link alle risorse:
AntiLeechModule_DomainNumber: indicare il numero delle righe AntiLeechModule_AllowedDomain_N inserite e quindi il numero di domini da autorizzare
AntiLeechModule_AllowedDomain_1
AntiLeechModule_AllowedDomain_2
AntiLeechModule_AllowedDomain_N: Riportare per ciascun dominio una riga nella forma AntiLeechModule_AllowedDomain_N dove N è il numero della riga stessa, impostando come valore il dominio autorizzato.
Nell'esempio vogliamo autorizzare 3 domini (primodominio.com, secondodominio.com e terzodominio.com)
Selezione delle directory che possono contenere file protetti:
AntiLeechModule_DirectoryNumber: indicare il numero delle righe AntiLeechModule_DirectoryPublic_N/AntiLeechModule_DirectoryPrivate_N inserite e quindi il numero di directory da proteggere
Per ciascuna directory da proteggere è necessario inserire due righe: AntiLeechModule_DirectoryPublic_N e AntiLeechModule_DirectoryPrivate_N.
AntiLeechModule_DirectoryPublic_N dovrà contenere il percorso relativo della directory pubblica a cui linkare i file .ext.aspx
AntiLeechModule_DirectoryPrivate_N dovrà contenere il percorso relativo della directory privata che conterrà i file .ext.exclude
Nell'esempio vogliamo proteggere 2 directory: /directory1/ che preleva i file da /directory1/secure/ e /directory2/ che preleva i file da /directory2/secure/
Selezione delle estensioni di file da proteggere:
Sarà necessario una riga <add verb=....></add> seguendo l'esempio, per ciascun tipo di file da proteggere.
3. Preparazione dei file da proteggere
In ciascuna directory protetta, sarà necessario rinominare i file aggiungendo la seconda estensione .exclude (ad es. nomefile.ext andrà rinominato in nomefile.ext.exclude) , a questo punto sarà possibile richiamare gli stessi file dalla directory pubblica aggiungendo l'estensione aspx (ad es. nomefile.ext andrà richiamato come nomefile.ext.aspx)
4. File supportati
Il sistema creato supporta i file .zip, .gif, .png, .jpg, è possibile inserire ulteriori estensioni seguendo le istruzioni riportate nei commenti del codice sorgente.
5. Problemi noti
Il sistema può funzionare in modo non corretto con il browser Internet Explorer 6, se viene attivata la compressione HTTP lato server per i file aspx.
Pubblicato da: Daniele Iunco il 06/04/2007
|
|
|