views:

366

answers:

3

I am using ASP.Net MVC. I have restricted access to the web site using ASP Forms authentication. However, the web pages contain links to pdf files on the server which I also want protected.

For example, the user can browse to foo.com and foo.com/account/logon. Once they logon they can access foo.com/category/bar which presents the view in bar.aspx. On that view is a link to foo.com/files/theta.pdf which loads up in the browser just fine. However, I don’t want foo.com/files/theta.pdf accessible from the browser unless the user has authenticated.

How do I prevent a user from accessing foo.com/files/theta.pdf directly from their browser without first authenticating at foo.com/account/logon?

+4  A: 

Pass the request through a controller, and return a FileResult. You can apply whatever security you want to the controller method, either by using the Authorize attribute, or by checking permissions inside the controller method.

There is an example of such code at this question, which illustrates how to return an image file. Just return your pdf instead of the image file, and use application/pdf as the MIME type.

Robert Harvey
Thanks. I changed the controller to accept a parameter identifying the file, then constructed the path and returned a FileResult. That had the desired effect of displaying the PDF. However, a user could still add the entire link in the browser and bring it up. I tried adding the location element to the web config as suggested by Charles but that didn’t do the trick (perhaps I did something wrong). I was able to get the desired effect however by adding a “deny” rule on that folder using IIS Manager. So now the user cannot display the PDF directly.
Jeff Rubingh
`However, a user could still add the entire link in the browser and bring it up.` -- That's why you add the Authorize attribute to the controller method, to restrict access to only those users that are assigned to the proper role. If the user types in an Url, access to which he is denied, he can be redirected to a Login or Unauthorized page instead of returning the `FileResult`. This is the same security you would add to *any* controller method to allow or deny access based on the user's assigned roles. More info here: http://nerddinnerbook.s3.amazonaws.com/Part9.htm
Robert Harvey
+2  A: 

If you want to restrict all access to the /files directory you could simply use a location element in your web.config to restrict access.

E.g.

<location path="~/files">
  <system.web>
    <authorization>
      <deny users="?" />
    </authorization>
  </system.web>
</location>

I should add that I agree with Robert and Rob for advanced security, but if you just want a simple solution this should do the trick. :-)

HTHs,
Charles

Charlino
A: 

Use FileResult, which I believe is a built-in ActionResult. This will send back binary data that you can have all kinds of authorization around:

http://msdn.microsoft.com/en-us/library/system.web.mvc.fileresult.aspx

Rob Conery