Click here to Skip to main content
15,885,546 members
Articles / Web Development / ASP.NET
Article

Method for Securing the Accessible Files

Rate me:
Please Sign up or sign in to vote.
4.67/5 (3 votes)
20 Dec 2007CPOL3 min read 24.3K   136   19   1
Downloading the files under asp.net authentication

Introduction

I find there are so many solutions on the internet which can solve the security file downloading problems. But when I encounter this kind of things, I still feel some updates will help a lot. So I write this post down, hope it will help u guys! ^_^ Coz CodeProject really helps me a lot! Here, I just give a brief introduction, so hope u have already known sth about how IIS and ASP.NET works and .ashx!

Background

In asp.net development, asp.net technology employes form authorization mechanism to provide content-level protection, which authorize the request at the initial status. More safety! But only to aspx, asmx, ashx, .config and etc, since the IIS only mapping these types of files to the aspnet_isapi.dll which can be processed under the security checking by asp.net form authorization. How to solve this kind of problem? Just change the mapping policy in IIS control panel, but if I can’t access it, what should we do? (some users put these contents on virtual server belonging to ISPs, which isn’t controlled by themselves). And this is not a good way that will slow down the processing speed of asp.net application. This problem has been solved out at IIS 7.0, which just merging the isapi.ll and aspnet_isapi.dll togather! ^_^ But I’m afraid that those ISPs will not provide this kind of advantages for free!

Another way is downloading the file whose file name has changed in the downloading period, which means u can set the file name to be complex enough that makes the clients can not guess out! But it’s hard to manage, not security enough and not depend on the excellent authorization of asp.net technology, isn’t it?

Using the code

Now what I do is just truncate some part of these two and then combined together! Let’s start! First, I need to put the files in the folder which is protected by the authentication mechanism asp.net provided!

// the web.config content protect the content in the specific folder

<authorization>
  <allow roles="webmaster" />
  <allow users="you" />
  <deny users="*" />
  <deny users="?" />
</authorization>

But only those aspx, asmx, ascx liked file would be protected, hoho, just change the file extension to aspx, ascx or asmx what ever u like! So the asp.net form authentication will apply on these files! But another question is when we change it to the original ones? When downloading!

How to change the file name when downloading?? Use this piece of code! ^_^
context.Response.AppendHeader("content-disposition", "attachment;filename=XXX");

So, 1st we change the file extension to aspx liked when uploading, 2nd we provide a HttpHandler to change the file extension back when downloading! So now u can directly tell the others ur file name but they can’t access! Better than change to a very complex file name which make u and the client will never guess out, isn’t it?

// Accomplished IHttpHandler Interface
// Changing the file extension back to the original one

public void ProcessRequest(HttpContext context) {
    
    // Get the Original File Path and Name

    string[] strSecurity = context.Request.QueryString["Fname"].Split('/');
    string strFileName = strSecurity[strSecurity.Length - 1];
    string strPath = HttpContext.Current.Server.MapPath("~") + @"\Docs\";
    if (!File.Exists(strPath + strFileName + ".aspx")) {
        context.Response.Write("ERROR! There's no such file in the specific folder!");
        context.Response.End();
    }
    
    context.Response.ContentType = "application/octet-stream";
    context.Response.Cache.SetCacheability(HttpCacheability.Public);
    context.Response.BufferOutput = false;
    
    // Start to transfer the file 

    FileStream stream = new FileStream(strPath + strFileName + ".aspx", FileMode.Open);

    int buffersize = 1024 * 16;
    byte[] buffer = new byte<buffersize />;
    int count = stream.Read(buffer, 0, buffersize);

    string htmlHeader = "attachment; filename=";
    htmlHeader += strFileName;

    // Change the file extension to the original one

    context.Response.AddHeader("Content-disposition", htmlHeader);
    while (count > 0) {
        context.Response.OutputStream.Write(buffer, 0, count);
        count = stream.Read(buffer, 0, buffersize);
    }
    stream.Close();
}

So we can just use a link like "http://url/FileHandler.ashx?Fname=XXX" to access the file more safely! There’s an real achievement on the project management part in my website, which u can directly go to have a test! ^_^ Good luck!

At the last time I mentioned that there’s still a security problem! Here I just try to solve it out! As we know, if the client, who has the right to access the FileHandler.ashx, he or she can directly provide a filename in Fname parameter whatever he or she like, and the code will provide the specific thing! Downside! If Fname=../XXX, then ur source code is unveiled! How to prevent this kind of attempting? There are so many solutions, here just provide one:

We can check the file which client requests is in the specific folder or not! Using System.IO.File.Exist(“XXX”) static method. So we just add some line at the beginning of ProcessRequest method to detect the file is in the specific folder or not! ^_^

History

Seems have been finished! ^_^ If u find any other security problems of this method or better solutions, don’t hesitate to leave me a message!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Program Manager Nanchang Kaifeng Software Limited
China China
Hoho!

Comments and Discussions

 
GeneralThank you. Pin
thomasdrago26-Feb-09 7:13
thomasdrago26-Feb-09 7:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.