I have some files in a "downloads" folder on my site. The only people who should be able to download the files are people who have purchased them. I have a "downloads.asp" page (classic asp) which asks for the visitor's receipt number. Their input is checked against my database to ensure it is legit. If it is legit, a list of their purchased products is provided on the page. Each list item is a link to the appropriate file, such as "http://www.mydomain.com/downloads/purchasedfile.msi". However, such a url could be handed to a customer's next door neighbor, who could then download the file without having purchased it.

Using the file manager provided by my webhosting company I find there are 3 types of permissions available to a folder: Authenticated, Application Pool, and Anonymous. Obviously I do not want to allow all anonymous users to access the files. I expected that using the Application Pool settings (allow read, allow execute) would enable anyone connecting to the files from my .asp page to automatically have the appropriate permissions (after they provided a legit receipt number), but that is not correct.

Furthermore, I don't even know how Application Pool permissions are set up. There does not seem to be an obvious place where I set up a generic account name or password, so I don't even have such things to provide from my .asp script. All my research tells me that accounts for an Application Pool are set up through IIS from the server itself. The server is my webhosting company's, not mine. How do I set up an account and it's password, and how do I provide those values from my .asp script?

What I would suggest is making it database driven for your needs. Depending if you want a user to register, purchase, and in the future, re-download, then use a database that stores your values. Something like below would be great:

Databases:
RegUsers
   UserName
   UserID
   UserEmail

DownloadFiles
   DownloadLink
   DownloadID
   PurchaseRequired
   NumberDownloads

UserFiles
   UserID
   DownloadID

Now, when a user registers, their information gets submitted into the RegUsers database. When you add a download to your site, add the link to the database with a random id, whether or not it is required to purchase to download (1=yes, 0=no [or just use yes and no!]), and the downloads set default to zero. Now when a user clicks on the link, or when you read out the page from the database, if the user has not purchased the download, a link to purchase should appear. When a user does purchase the download, add the UserID and DownloadID to the UserFiles database. Now only that user can download that file. To help prevent users from seeing your .zip files or what not, use a blank asp page with just a back-end code referencing the file. If you need help let me know.

Hi SheSaid,

I really appreciate all the effort you put in on your response. It's reassuring to know someone is interested in discussing this with me.

The thing is, the site is database driven. When the user arrives at the downloads.asp page of my site they must first provide the email address used for their purchase and their receipt number. The downloads page checks the database and retrieves a list of their purchases from the database, displaying them to the user as list of links to each purchased file. The problem I have with this is that whenever a link is displayed, passing the mouse over it shows the actual web address of the file in the status bar of the web browser. A user could then simply write that address down and give it to their next door neighbor, who could type it directing into their address bar and download the file for free.

So the only solution I could think of is to put the files in a protected folder on the website so that when someone attempts to download the files it would only work from the downloads.asp page, which would provide some kind of "authenticated download user" credentials whenever someone clicks a link. In reality, obviously clicking a link would not give control to the .asp code anyway, so I display submit buttons that they can click instead of links. This not only gives the .asp code control of what happens next, but also does not display the link address in the status bar. This works well, actually...and even makes the need for authentication to be less pressing since the file address doesn't show...but it does not solve the problem perfectly because it raises another problem: redirect prevents other code on the page to not run. Once the server encounters the redirect, any other code that would have run gets discarded and the redirect takes precedence...causing my database to not be updated with information about the download (date and time, number of downloads, etc.). Since redirect prevents other code from running, this cannot be the solution.

So I'm back to square one. If I display a link, the address to the file is visible for the whole world to see (or since this user is verified as a customer...for them to share with the whole world). The only way I can see to prevent that from happening is to have credentials provided from my website. Typing the address directly to the file in a web browser would result in the user being prompted for credentials...which they wouldn't have. Now I just need to figure out how to provide them from the .asp code. It seems like that should be possible in the same way you provide a user name and password for an ADO connection. Maybe I'm wrong.

Any ideas? Again...the real problem I'm trying to overcome is the fact that the direct address to the file shows in the status bar. If you have any idea how to prevent that, that sure would be easier.

Thanks for reading.

As somewhat of an update, I did try changing the statustext on mouseover, but that is dicey. First of all, if I try to set the text to something other than the link destination, my browser (IE7) simply displays nothing. I'm guessing that is the result of some kind of update to technology which no longer allows us to mess with statustext. But the fact that it displayed nothing rather than the destination of the new text I'd told it to display was still a minor step forward: it doesn't display the destination.

Unfortunately, just right-click on any link and you can "copy shortcut". Paste it into an email and share it with family and friends. :-(

The code on the downloads.asp has to run. It subtracts one from the buyers' "downloads remaining" count and logs their download. The direct link to the file itself cannot be visible. The redirect causes the code on the page to not run. Server.execute won't work because it only executes an .asp page. If I put the redirect on another .asp page and server.execute it from downloads.asp, the redirect on that page never returns control to the executed page, so control never returns to downloads.asp.

Argh.

You can set your downloads into a page that is referenced with their email, receipt number, and the download chosen. Then on the page that requests it, check the database to make sure the email and receipt number is correct for the download link. You can have it done on the same page if you wish, but I would suggest not in order to give the user some kind of notification that his request has been made (and a proper link to the file if the page doesn't automatically initiate the download)

Put the links into a form with each download link having a unique name (potentially the download name? :) ) and also create a unique session id for the user storing it into a hidden input field and session variable. Put the user's email and receipt number in the current session variables. When the user clicks the link and goes to the download page (we'll call it download.asp), in the download.asp page check the users email and receipt number to the corresponding download, then verifies if the session variable is true and compares it to the hidden input field in the form it just submitted. If it passes, then initiate the download. And if it doesn't initiate within 5 seconds, provide a link that refreshes the page. You can do all this or just do a URL Rewrite with Apache. This way if you do a url rewrite, when someone times in your ZIP url (http://yourdomain.com/files/file.zip), it rewrites to.. let's say http://yourdomain.com/registereddownload/download.asp?file=file.zip. Then your download.asp file runs the code. There are many ways, but all take time and lots of code. Your best bet is to create the page and pass the download link

Something like this should work:

Dim rndID
Session("rndID") = rndID
Session("email") = Request.Form("email")
Session("receipt") = Request.Form("receipt")
response.redirect("/purchases.asp") 'or some page after login

Now on your purchase.asp page:

<script type="text/javascript">
function downloadfile(id) {
if (id == "") {
  return false;
} else {
  document.form.purchases.hiddenLinkID.value = id
  document.form.purchases.submit()
}
</script>
<form name="purchases" id="purchases" action="/download.asp" method="post">
<input type="hidden" name="hiddenID" id="hiddenID" value="<%= Session("rndID") %>" />
link with onClick="javascript:downloadfile('linkID')"
link with linkID
<input type="hidden" name="hiddenLinkID" id="hiddenLinkID" value="" />
</form>

Now on your download page:

'check your database and compare the email and receipt for extra security.
if Len(Session("rndID")) > 0 and Request.Form("hiddenID") <> "" then
  if Session("rndID") = Request.Form("hiddenID") then
    Dim strFile = Request.Form("hiddenLinkID")
    if Not IsNull(strFile) and strFile <> "" then
      'download works here
    else
      response.redirect("login.asp")
    end if
  else
   response.redirect("login.asp")
  end if
else
  response.redirect("login.asp")
end if

Now obviously the code isn't tested, and should only be used as a reference. But that is something that would work for you.

Thank you SheSaid. You have again made a real effort to help me out here. I can't tell you how much I appreciate your time.

I'm reviewing what you've written here and am trying to digest it and apply it. I'm not really slow, but I'm meticulous. :-)

I have one big question I need to ask, though. I've encountered tons of javascript in my research travels, and even here in an ASP environment you have offered some javascript code as a solution to part of the problem. I'm new to internet programming (I'm an old school VB programmer who likes vbscript for obvious reasons) and am coming under the impression that it is impossible to create a site that does not use javascript. Is it true that I must learn that language in order to run a website? Is there no way around it? Since you've offered javascript as a solution I have to assume there is no other way to accomplish what that script does. Heck...I'm not entirely clear on *what* that portion of your script does. I have to study it a while. It can't be done with vbscript? It's the onClick part that's the culprit, isn't it? A submit button doesn't accomplish the same thing? I have to assume there's a reason you chose to use javascript. I simply don't know why.

In any case, thanks a ton. I'll review what's here and get back with you if I have any questions. If all goes well I'll surely let you know that too.

Take care.

javascript isn't required at all on this actually, I am just trying to hide the url fully. You can, instead of using javascript, just post the link to the download page like the following:

download.asp?dl=/jujus/downloads/juju.zip

But by using javascript, you can post it to a hidden variable without the user ever seeing it. Javascript is mainly for interactivity on the web browser. Most sites use javascript as it is main language that edits information via the web browser that doesn't require the server's processing time. It saves enormous amounts of bandwidth, memory, and processing time. It's a very good language as probably 90%+ of websites created today use javascript. But of course you can create it without javascript just fine, just requires more work and uses up more resources on the server. If you wish to avoid javascript, just post the information to your download page like the following:

<a href="linktodownloadpage/download.asp?dl=downloadlinkhere&session=kjsdLDojlksD99883LSkjdsl">Download 1</a>
in asp:
<a href="/download.asp?dl=<%= rsObject("downloadlink") & "&session=" & Session("session") %>
[this works fine, just the user will see your download link, or download ID, whichever you choose to store and how your site is structured]

'' Onto the download page
<%
if Request.QueryString("session") <> "" then
  if Session("session") = Request.QueryString("session") then
    'do database search for username and email
    'if valid, then execute download
    'else
    'redirect or post error
  else
    'redirect or post error
  end if
else
  'redirect or post error
end if
This article has been dead for over six months. Start a new discussion instead.