jueves, 29 de abril de 2010

ASP.NET - Imagenes solo para usuarios autentificados

Vamos a ponernos en el caso de que tenemos una galería privada de imágenes y no queremos que alguien las esté referenciando en su sitio web sin que nosotros lo aprobemos… mejor dicho, para que visualizen ciertas imágenes tienen que estar autenticados en el sistema. Si resultara que no estás autentificado, en lugar de ver la iamgen que esperabas, verás esta imagen:
nodisponible nodisponible.png
Sobre este tema siempre he visto tremendas sábanas de código y en este caso, creo que la solución es muy simple.
Lo que propongo es usar un archivo httpHandler para devolver las imágenes… en lugar de mostrar la ruta completa de la imagen en el control IMAGE. Entonces cada control IMAGE debería estar solicitando la imagen de esta manera (en la página aspx):
<form id="form1" runat="server">

<asp:Image ID="Image1" ImageUrl="~/Handler.ashx?img=MI_IMAGEN.png" runat="server" />

</form>

Lo que estamos haciendo es pasar el nombre del archivo handler.ashx + un parámetro querystring en donde le digo cuál es el nombre de la imagen que quiero displayar.

Y el código del archivo handler.ashx sería:

Imports System.Web
Imports System.Web.Services

Public Class Handler
Implements System.Web.IHttpHandler, IRequiresSessionState

Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

Dim Path As String = context.Server.MapPath("~/images/")
Dim img As String = context.Request.QueryString("img")

'si el usuario no está autentificado
If  IsNothing(context.Session("UserID")) Then img = "nodisponible.png"

        context.Response.ContentType = "image/png"

        context.Response.TransmitFile(Path & img)

End Sub

ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property

End Class

Dense cuenta que este handler puede acceder al objeto sesión porque también implementa IRequiresSessionState (más información).

Enter las ventajas que este método brinda tenemos:

1.- El usuario nunca sabrá cuál es la ruta en donde se almacena la imagen.

2.- Las imágenes no podrán ser referenciadas directamente en otros web sites (hot linking)

3.- Sólo la pueden ver usuarios autentificados.

4.- Se pueden hacer más verificaciones adicionales si se requieren.

Para este ejemplo básico he asumido que todas las imágenes están en formato png…

context.Response.ContentType = "image/png"

tú puedes mejorar el método para que sirva todo tipo de imágenes… aunque poner el tipo de salida no es necesario, el browser reconocerá el tipo de contenido… pero para mejor comprensión se estila poner.

En este post hemos demostrado un método para servir imágenes sólo a usuarios con una sesión autentificada. Y las imágenes simplemente son recuperadas de una ruta física en el servidor… podríamos hacer otro post en donde las imágenes se recuperen de la base de datos e igual se muestren a través del handler…, no les parece?
 ;)

2 comentarios:

Unknown dijo...

Excelente articulo.
Solo tengo una pregunta he de suponer que la sesion UserID se le ha ya asignado previamente el identificador del usuario?

Saludos!

Segundo Serrano dijo...

Hola Deus-Diew,
así es... estamos suponiendo que el usuario previamente se ha autentificado y su id se está guardando en esa variable de sesión.

Saludos