As others pointed out, URLs are meant to be public. There is no reasonable way to completely hide them from the user.
However, you can use MVC to control access to resources, such as physical files.
By default MVC does not serve physical files, IIS serves them directly. Assuming that your file is physically located in the /download/document/
virtual directory, start by blocking any direct access to the folder through your root web.config
file.
<location path="download/document">
<system.web>
<authorization>
<deny users="*" />
</authorization>
</system.web>
</location>
This ensures that no user (whether logged in or not) can access the file directly through IIS.
Then, you can use a controller action method in conjunction with the [Authorize]
attribute to control who has access to the file.
public class SecureDownloadController : Controller
{
[Authorize]
public ActionResult Document(string id)
{
return File(@"D:\wwwroot\documents\download\" + id, "application/pdf");
}
}
The above will allow any logged on user to access the file at the URL http://localhost:20870/securedownload/document/d47a1c96-e4d7-423b-aa83-76537c392ad2.pdf
.
IMPORTANT: Never use a real location for the file in the URL. IIS will favor a physical location to an MVC controller action, so if the physical file exists you will get an error. You probably don't want the user to know the physical location of the file anyway.
You could further restrict it to a specific user role or roles by using:
[Authorize(Roles = "Admin,SuperUser")]
Alternatively, you could subclass [Authorize]
attribute and use some other way to secure the file, for example, passing a hash code through the HTTP headers.
Another possible alternative: Generate the PDF as a stream rather than using a physical file that is persisted on the disk. This ensures there is no physical path where the file can be accessed - it can only be accessed through a controller action method. It also ensures you never have to clean up a directory of one-time-use PDF files.
References: