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!
<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?
public void ProcessRequest(HttpContext context) {
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;
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;
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!