Ask Ben: Hiding Customer-Specific Image Paths

Posted November 13, 2008 at 10:02 AM by Ben Nadel

Tags: ColdFusion, Ask Ben

How to hide my folder images? Ben, I have many folders with images for my customers

/customer1/images
/customer2/images
/customern/images
...etc

is the way to hide my path (or create temp path) from url donwload images page? Original Code:

<a href=/customer1/image1.gif>donwload pic</a>

This is critical.. customer change url and get images from another customer.. Hide Path, some like this...

<a href=/ASDE-FDRE-FGRT/image1.gif>donwload pic</a>

Create a field into DB and create virtual path (IIS) is a one solution (ASDE-FDRE-FGRT = customer1) ... is there another solution with cf? For any comments.. thanks

I have never worked much with virtual paths or anything like that because most of the time, I don't have access to that piece of functionality (IIS). Additionally, if this is a situation that is changing regularly (adding or deleting new customers), I tend to like having a very dynamic solution. To me, this means an all-ColdFusion solution. The first thing that popped to mind was piping all image requests through a ColdFusion page that streams the image back to the client.

So, for example, instead of having a URL like:

/customer1/image1.gif

... you could have:

/images/?image1.gif

What this assumes is that there's an "images" directory that has an index.cfm page that is using the query string value (image path) to return the appropriate image to the client. The code for this might look something like:

  • <!---
  • Param the image path. By default, our path is going
  • to be everything past the query string delimiter.
  • --->
  • <cfparam
  • name="URL.image_path"
  • type="string"
  • default="#CGI.query_string#"
  • />
  •  
  •  
  • <!---
  • Get the image directory path based on the current customer.
  • This assumes that the "current" customer is in some sort
  • request-based variable.
  • --->
  • <cfset strImageDirectory = REQUEST.ImageDirectory />
  •  
  • <!---
  • Now, we can get the full path of the image (this is the
  • fully expanded, server path, not a URL path).
  • --->
  • <cfset strFullImagePath = (strImageDirectory & URL.image_path) />
  •  
  •  
  • <!--- Set header values. --->
  • <cfheader
  • name="content-disposition"
  • value="attachment; filename='#ListLast( URL.image_path, "\/" )#'"
  • />
  •  
  • <!--- Stream the image to client. --->
  • <cfcontent
  • type="image/#ListLast( URL.image_path, '.' )#"
  • file="#strFullImagePath#"
  • />

In the above code, you will see that the actual image directory is stored in a REQUEST-scoped variable, REQUEST.ImageDirectory. By doing it this way, we can change this value on a page-request basis. Each user might be a different customer and will therefore have a different REQUEST.ImageDirectory property value. The image, as taken from the query string, is then streamed to the browser using ColdFusion's CFContent tag.

By doing it this way, not only is the location of the image kept hidden, it doesn't even need to be a web-accessible directory. ColdFusion's CFContent tag can stream any file that the server has access to, even if it is not in a public directory.

There are some down sides to using CFContent to stream data back to the client, but as Eric Stevens pointed out, ColdFusion 8 seems to use CFContent quite efficiently. I hope that this suggestion can help in some way, or perhaps provide some inspiration.



Reader Comments

Nov 13, 2008 at 1:50 PM // reply »
66 Comments

I do something similar when delivering dynamic documents too. If you're really paranoid, I suppose you could also throw in a cffile to copy the image to a temp dir, but probably wouldn't be necessary.

Since your working with images, I might also throw in a IsImageFile in there too.

<cfif IsImageFile("strFullImagePath")>
<cfheader ... />
<cfcontent ... />
<cfelse>
Error message here
</cfif>


Nov 13, 2008 at 2:22 PM // reply »
1 Comments

I would be careful of cfcontent - depending on the level of traffic and size of images your are serving it can quickly bring your server grinding to a halt as a thread is consumed until the image transfer is complete.

It just takes a few users with slow connections requesting large images.


Nov 13, 2008 at 2:29 PM // reply »
11,238 Comments

@Steve,

Good point. Plus, there would probably need to be some additional path scrubbing to make sure no one tried to stream anything they are not supposed to.

@Johans,

I suppose that as the sites get bigger and more complex, the bigger and more complex your solution needs to be. I would assume that as the site gets more traffic, one might consider getting static file servers and other things that help to alleviate like concerns.

But, yes, one should be cautious.


Jim
Nov 13, 2008 at 5:00 PM // reply »
16 Comments

Hi Guys,

I know CF can do this, but why? It's like using a fork to eat soup. Sure you can do it, but it's slow.

Check out Isapi rewrite / mod_rewrite, if you're using IIS / apache. You can set up rules to 'mask' URLs. If you're using isapi rewrite, the rule in this case would be something like:

RewriteMap user txt:user.txt
RewriteCond %{REQUEST_URI} ^/([^/]+)/?(.*)?$
RewriteRule .? http://www.test.com/${user:%1}/%2 [NC,L,P]

Then in your user.txt file
ASDE-FDRE-FGRT customer1
ASDE-FDRE-FGRG customer2
... etc.

HTH,

Jim


Nov 13, 2008 at 5:06 PM // reply »
11,238 Comments

@Jim,

I like the re-write solution, but it seems that the client paths are not obfuscated in any way. Meaning, someone can just start guessing at URLs. By hiding the "current client" in the ColdFusion page request, you can pipe ALL requests to the same place and have the ColdFusion logic determine which client is actually being used.


Jim
Nov 13, 2008 at 5:38 PM // reply »
16 Comments

Ah, I see now. The author is trying to implement a security model, not a obfuscation model.

Having said that, there's no reason the author can't use both tools. Plus it would save the two costly listLast function calls.

for instance:

Isapi re-write rule:
RewriteRule ^/images/(.*) /images/?image_path=$1 [NC,L,P]

Then in the image.cfm
Add your code, but make the URL.image_path EQ plus whatever security checks that are needed.


Nov 13, 2008 at 5:40 PM // reply »
11,238 Comments

@Jim,

I didn't mean to shoot your idea down - one of the option's suggested was pure obfuscation, which the ISAPI Rewrite could definitely help with.


Nov 17, 2008 at 10:47 AM // reply »
12 Comments

This is actually a pretty important topic for quite a few people. The issue comes also when concerned about resource leaching. If you have a Linux machine you can solve a lot of the problem by an .htaccess on your images directory but if not you want to be able to protect other resources, perhaps not even make them web-accessible except to valid or logged on users.

In order to restrict access to only those people with current sessions you need to have some means of delivering (streaming) the content after determining whether a valid session exists.

How, if not using cfcontent or the java equivalent, do you protect the resources AND hide from the user its true location?


Nov 17, 2008 at 4:49 PM // reply »
9 Comments

This is an interesting post, Ben how would your solution measure in terms of speed/caching?

If I request this
/images/image01.jpg
it will load fully the first time but the second time it may go directly to local cache depending on browser settings, improving performance.

Wouldn't this
/images/?image01.jpg

load an image every single time?


Nov 17, 2008 at 5:23 PM // reply »
11,238 Comments

@Fernando,

I believe that caching works on the entire URL, not just the script name. As long as the query string doesn't change, I think the caching will know how to include it.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
May 14, 2013 at 6:57 PM
The UX Of Prototyping: Low-Fidelity Is The New High-Fidelity
@Phillip, I'm not sure I follow what you mean? Are you saying that you looked at the list of widgets provided by the jQuery UI and let that be your style guide? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools