I want users to see an image as part of a web page but I want to avoid them accessing a image directly. This could, say, give clues in the URL about what user they're linked to (a flaw I've seen in one facebook application).
How can I go about monitoring image access and/or preventing direct access to images (through url rewriting for example...)?
Solutions suggested so far:
- Use of headers (reliable?)
- Making access to images more difficult (ex: set image as div background).
- ...
If I may, something that again isn't bullet-proof, but tricks many is to use the image as a background. In your HTML place an image tag filled with a special transparent 1px by 1px gif (blank.gif circa html table layouts) and size it to the dimensions of your actual image. Then set the background image of it to be the actual image. This will trick many users who only know how to right click to download/get the URL of an image.
I know this won't help if the user Print Screens (but neither will any method), but it is a solution for those less knowledgeable users. Plus, sites like Youtube already employ this method so if it's good enough for Google, I'd say it's good enough for you or me!
EDIT: Please excuse my total lack of consciousness to this already being posted as a comment. I began writing before that was posted.
There is not bullet proof way. However, you can use heuristics. Inspect the following headers:
Referer
-- this header will be present is the image was requested by the browser as a result of<img>
tag or CSS. This header will be empty if the image was requested directly (by typing the URL in address bar). If this header contains another domain then that other website hot-linked your image. Note that this is the expected behavior but it is not guaranteed that every browser will behave this way.Accept
-- this header will contain a string such asimage/*
when image was requested because browser found it embedded in HTML tags or CSS. When someone requests the image directly by typing in the browser, you'll find values such astext/html,application/xhtml+xml
etc. This is because browser does not know what to expect when it requests http://website.com/someimage.jpg; hence it will preferably ask fortext/html
content.In Apache, you can check (and match) HTTP headers to determine whether content is accessible or not. I am not sure about other platforms, but you can write a generic proxy script for serving images.
Edit
If the image URL reveals information that you do not want disclosed, you can obfuscate it by using hashes or encryption. So instead of serving content such as:
You will write:
You'll need to write a script that sends the corresponding image to the browser.
As said, there is not silver bullet for doing this (you can't prevent the user to make a screen capture for example)
But, if you want to protect your pictures against anonymous access, you can use a php "proxy" that will check if the user is allowed to see that pic, and then load it.
Here is a very simple sample code for such a proxy. If you really want to protect your images store them outside your document root.
If you want to test this script :
Hope that helps !
Here's an idea that may work, although I've not really thought it through too much, and haven't tried it:
For example, instead of:
<img src="www.mysite.com/mypage/myimage.jpg">
...generate a one-time-key and store that in a lookup table, so that it refers to your image:
4e33fd162fe95 => image.jpg
...then generate your page using that OTK instead:
<img src="www.mysite.com/mypage?image=4e33fd162fe95">
When the server receives a request for that image, send the image, and delete the OTK. This means that every request for the page generates a new OTK. Trying to use that URI for the image again will not work.
This has some obvious caveats in terms of performance, as client-side caching would no longer work, and it will place some overhead on the server. There are probably other caveats too.