Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Restricting files download using HTTP Handler based on conditions

0.00/5 (No votes)
22 Jul 2013 1  
Restrict file downloading using HTTP handler if session doesn't exist.

Introduction 

In this article I have elaborated how to restrict file downloading from a website using HTTP handlers. There are alternate ways to restrict file downloading, e.g., using Forms authentication. It depends upon your solution and the architecture that best suits you. So in this article I am using the HTTP handler approach for restricting file downloads if a user session doesn't exist.

Background

HTTP Handlers:

(MSDN definition)

An ASP.NET HTTP handler is the process (frequently referred to as the "endpoint") that runs in response to a request made to an ASP.NET Web application.

So HTTP handlers are extension based processors, for example, in IIS server an HTTP handler which entertains the request for a .aspx extension is ISSAPI.dll (in classic mode). We can also create custom handlers for required extensions (.pdf, .jpg, .doc) by implementing the IHttpHandler class and registering in the handler section of IIS server. So come and have a trip with me to handlers so that I can tell you about how to create, implement, and register HTTP handlers.

How to create an HTTP handler 

There are two ways to create HTTP handlers:

1) To create an HTTP handler create a C# class file and inherit from the IHttpHandler interface, implement both the method and property below.

public void ProcessRequest(System.Web.HttpContext context)
{
 
}
public bool IsReusable
{
  get
   {
    return true;
   }
}

2) Right click on the solution in the Solution Explorer tab and then select Add New Item and select Generic Handler from the template. This will create a .ashx file that is basically nothing but a wrapper of the class file that has implemented the IHttpHandler interface.

In my example I will use the first approach.

If you are new to HTTP handlers then the following links will provide you with the basics concepts:

Using the code

A little elaboration about the attached demo website follows:  

Pages: I have created a simple web site in ASP.NET web forms. I have a login.aspx page, LogedInIndex.aspx page, and an UnloggedInIndex.aspx page. I have hard coded the User ID and the password for the login. (User ID: Tanzeelur, Password: Rehman). As it is just a demo there is no need to implement a good UI layout, enterprise level logic, and securities on the login page . The pages LoggedInIndex.aspx and UnloggedInIndex.aspx both have the same links to the same files (pdf, docx, xlsx). In the UnloggedInIndex.aspx page you can see the links to the files but cannot download, because when you request for the file, an HTTP Handler will interrupt and check for the session; if the session doesn't exist then it will redirect to the login.aspx page, otherwise it will allow you to download the file. On the other hand, in the LoggedInIndex.aspx page when a user is logged in properly in the login.aspx page, a session will be created and the page will be redirected to LoggedInIndex.aspx (so here file downloading will be accessible because the session exists).

C# class files: I have two class files in my App_Code folder: TestingHandler.cs and MIMEType.cs.

TestingHandler.cs: The file TestingHandler.cs is basically the Handler that has implemented IHttpHandler (an interface, which a class must inherit to be an HTTPHandler). TestingHandler.cs has also implemented ISessionReadOnlyState, without this the ISessionReadOnlyState interface implemented Session object in the handler will always return null, due to which an exception will be raised.

Testing handler code is implemented below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.SessionState;
 
/// <summary>
/// Testing Handler to restrict file downloading based on if user session doesn't exist.
/// for instance my User session will be Session["User"]
/// </summary>
public class TestingHandler:IHttpHandler,IReadOnlySessionState
{
	
    bool IHttpHandler.IsReusable
    {
        get { return false; }
    }
 
    void IHttpHandler.ProcessRequest(HttpContext context)
    {
       
       if(context.Session["User"]==null)
           context.Response.Redirect("~/login.aspx");
 
           var filExtension = GettingExtension(context.Request.RawUrl);
           context.Response.ClearContent();
           context.Response.ClearHeaders();
           context.Response.ContentType = MIMEType.Get(filExtension);
           context.Response.AddHeader("Content-Disposition", "attachment");
           context.Response.WriteFile(context.Request.RawUrl);
           context.Response.Flush();
 
    }
    public string GettingExtension(string rawUrl)
    {
       return rawUrl.Substring(rawUrl.LastIndexOf(".", System.StringComparison.Ordinal));
    }
}

Let's have a glance over the above code. As I have mentioned in the beginning of this article, to an create HttpHandler we have to implement IHttpHandler. The IsReusable property and the ProcessRequest method belong to the IHttpHandler interface. Your logic always go in the ProcessRequset method of the handler. In the ProcessRequest method I am checking for session["User"]; when it is null, I am redirecting it to login.aspx. When the user Session exists, it allows the file to be downloaded to the client side.

In the Handler I have used the MIMEType.Get(filExtension) statement, which I will discuss below.

MIMEType.cs (Mime Type information on Wikipedia)

This class has a readonly Dictionary<String, String> MimeTypeDict property having most MimeTypes of file extensions. The static function Get(filExtension) returns the MIME type based on the extension of the file requested.

Here I will thank Mr. Sameul Neff for posting this on StackOverFlow. Some of the code from MIMEtype.cs is listed below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
/// <summary>
/// Summary description for MIMEType,
/// This code is the organized version of the answer posted by Sameul Neff
/// on stack over flow Check here http://stackoverflow.com/a/4259616/1142645 
/// </summary>
public class MIMEType
{
    
    #region MIME type list
    private static readonly Dictionary<String, String> MimeTypeDict = new Dictionary<String, String>()
    {
            {      "pdf", "application/pdf" },
            {     "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" },
            {     "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }
          
    };
        #endregion

    #region Get
    /// <summary>
    /// Returns the mime type for the requested file extension. Returns
    /// the default application/octet-stream if the extension is not found.
    /// </summary>
    /// <param name="extension"></param>
    /// <returns></returns>
    public static String Get(String extension)
    {
        return Get(extension, MimeTypeDict["bin"]);
    }

    /// <summary>
    /// Returns the mime type for the requested file extension. Returns the
    /// specified defaultMimeType if the extension is not found.
    /// </summary>
    /// <param name="extension"></param>
    /// <param name="defaultMimeType"></param>
    /// <returns></returns>
    public static String Get(String extension, String defaultMimeType)
    {
        if (extension.StartsWith("."))
            extension = extension.Remove(0, 1);

        if (MimeTypeDict.ContainsKey(extension))
            return MimeTypeDict[extension];
        else
            return defaultMimeType;
    }
    #endregion Get

}

How to register your Handler in IIS

Now it is time to register your handler in IIS, there are two ways:

  1. Using the interface of IIS. Click on your site -> in the IIS section, open Handler Mappings -> in the Action pane at the right most side of the interface -> click Add Managed Handler  -> Add your handler as shown below. By doing this it will add the handler in the web.config file. 
  2. The second method is by adding your handler in the handlers section of the web.config file. I have added mine in the web.config as shown below.  
  3. <system.webServer>
       <handlers>
          <add name="FileXlsx" path="*.xlsx" verb="*" 
            type="TestingHandler" resourceType="File" preCondition="integratedMode"/>
          <add name="Filedocx" path="*.docx" verb="*" 
            type="TestingHandler" resourceType="File" preCondition="integratedMode"/>
          <add name="FilePdf" path="*.pdf" verb="*" 
            type="TestingHandler" resourceType="File" preCondition="integratedMode"/>
        </handlers>
    </system.webServer>

That's all! I have added the demo application with the article. Feel free to query if there are any issues regarding the article or the attached demo application.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here