2
votes

I have an ASP.NET MVC application for which I store uploaded content files in a virtual directory. This virtual directory is directly underneath my MVC website in IIS.

My problem is that the virtual directory allows anonymous access. Anyone, logged in or not, can type in a public URL to my virtual directory and read the files in it. Is it possible to configure IIS (or something else) in a way that forces any requests to this virtual directory to run an authentication/authorization routine before allowing access?

Is this something I can configure in my website's web.config, or does the request never hit any server side code in this case? If it never hits server side code (and feeds the request directly to IIS), how can I change my implementation to require my site to authenticate/authorize and then serve my file.

Thanks for your help!

2

2 Answers

4
votes

I don't know that this is possible exactly how you requested it. But, I do know of a way you can do this using a different method. Maybe it will work for you.

The idea is to store the secured files in a folder that is not available from the web (not a virtual directory). Then, have a method on a controller like Controllers/DownloadController.cs that handles user authentication and file serving. Here's a sample method that can retrieve a file from c:\myfiles:

Controllers/DownloadController.cs (action method only):

[Authorize]
public FileResult Download(string filename)
{
    //get content type from file extension
    var contentType = getContentTypeFromExtension(filename);

    //return file with filename as third argument to 
    //   trigger browser's download bahavior
    return File(Path.Combine(fileFolder, filename), contentType, filename);
}

[Authorize]
public FileResult Open(string filename)
{
    //get content type from file extension
    var contentType = getContentTypeFromExtension(filename);

    //return file without download filename so that 
    //   the file is opened in browser (if possible)
    return File(Path.Combine(fileFolder, filename), contentType);
}

//method to get content type of file from registry using file extension
static string getContentTypeFromExtension (string fileName)
{
    string contentType = "application/unknown";
    string ext = System.IO.Path.GetExtension(fileName).ToLower();
    Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
    if (regKey != null && regKey.GetValue("Content Type") != null)
        contentType = regKey.GetValue("Content Type").ToString();
    return contentType;
}

fileFolder variable should be defined at the class level. I took it out because it was messing with the code formatting. :)

0
votes

If you are running IIS 7 or better, with integrated authentication, then the uploaded content will be running through the ASP.NET runtime so all the normal authentication tricks work--just add a web.config to the folder to enforce some security.

IIS 6 or earlier presents different challenges. A better idea is to "front" the files with a HTTP handler that grabs them out of a folder so that your files are protected by the runtime.