5

We're currently using folders inside webroot to store images and videos which we're loading in views (using the usual html image helper) that require log in.

How can I prevent outside visitors from just doing a site.com/img/photos/1.jpg url and having access to the images? From what I understand I can't really use media views to render an image inside a proper view, and I can't figure out if there's a solution through htaccess manipulation.

Which is the best practise for this? Perhaps choosing to go with a non-webroot folder would be best (although that would make it harder in the file-storing part)?

As poncha suggested, I tried editing the main .htaccess file into this

<IfModule mod_rewrite.c>
   RewriteEngine on
   RewriteCond %{HTTP_REFERER} !localhost
   RewriteCond %{REQUEST_URI} ^app/webroot/img/
   RewriteRule .* / [L,F]
   RewriteRule    ^$ app/webroot/    [L]
   RewriteRule    (.*) app/webroot/$1 [L] 
</IfModule>

But the rewrite base line seems to be forbidding access to the whole site, and without it there seems to be no change in img access.

Edit 2: Editing the htaccess inside webroot:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php [QSA,L]

# this RewriteCond is needed to avoid rewrite loops
RewriteCond %{REQUEST_URI} !^/app/webroot/
RewriteRule (.*) app/webroot/$1 [L,R]


RewriteCond %{HTTP_REFERER} !127.0.0.1
RewriteCond %{REQUEST_URI} ^/app/webroot/img/
RewriteRule .* - [L,F]

</IfModule>
dot
  • 61
  • 7

1 Answers1

2

This checks if Referer http header is set to something containing your domain, and denies access to img/ folder if not.

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_REFERER} !site.com
RewriteCond %{REQUEST_URI} ^img/
RewriteRule .* / [L,F]

Note: it is easy enough to "break" this protection if someone wants to steal your content, however, it does prevent hotlinking without the need to produce some sort of script that would pass thorugh all the images/videos to check if access should be granted.

EDIT:

In case your website is not in /, You have two options:

  1. Change RewriteBase to reflect the base uri of the site (eg RewriteBase /app/webroot/)

  2. Change RewriteCond to reflect the path from / (eg RewriteCond ^app/webroot/img/)

The second option is preferred in your case because you have other rules there

EDIT2:

In your case, the whole set should look like this:

RewriteEngine on
RewriteBase /

# this RewriteCond is needed to avoid rewrite loops
RewriteCond %{REQUEST_URI} !^/app/webroot/
RewriteRule (.*) app/webroot/$1 [L,R]

RewriteCond %{HTTP_REFERER} !localhost
RewriteCond %{REQUEST_URI} ^/app/webroot/img/
RewriteRule .* - [L,F]
poncha
  • 7,726
  • 2
  • 34
  • 38
  • 1
    Should I apply this on the main htaccess file, outside the app folder? Also I'm currently working on localhost under localhost/test, is this the url i need to replace `site.com` with? And finally, where do those lines combine with the pre-existing `RewriteRule ^$ app/webroot/ [L] RewriteRule (.*) app/webroot/$1 [L]`. Thank you – dot Jun 26 '12 at 11:53
  • 1
    @nepo **1**. this should be either in your `VirtualHost` configuration (in `httpd.conf` or per-vhost config file - depends on distribution) OR in `.htaccess` in the document root (where your site / reaches), **2**. yes, your base uri (probably without the http:// since you might use https) should be instead of `site.com`, and **3**. they should go before those pre-existing lines – poncha Jun 26 '12 at 12:03
  • Hm, the `RewriteBase /` line seems to be forbidding access on the whole site, although oddly enough I can still access the image folder using `http://localhost/test/app/webroot/img` – dot Jun 26 '12 at 12:08
  • if your site is not in `/` , then `RewriteBase` should also be there... OR include the path in `RewriteCond`. you mentioned in original posts that the urls you wanted to protect were of form `site.com/img/photos/1.jpg` – poncha Jun 26 '12 at 12:09
  • I've brought my site on the localhost instead of localhost/test to make it possibly slightly easier, but the folder is still viewable. Note that the preexisting rewrite rules turn localhost/img/ into localhost/app/webroot/img (as you probably have picked up I have no experience with htaccess editing so I'm not sure if that helps) Check my edit to see the current form of .htaccess – dot Jun 26 '12 at 12:31
  • What do you mean I don't need the old rules? They're the ones specifying the base folder is app/webroot. They're the default cakephp rules. – dot Jun 26 '12 at 13:15
  • but the base folder isnt `app/webroot` anymore? or is it? if it is, see the `EDIT` part of the answer above ;) – poncha Jun 26 '12 at 13:16
  • All I did was take my files inside wamp/www/test and put them in wamp/www. So now when I want to access the img folder in webroot I type localhost/img instead of localhost/test/img. Nothing else changed, the chain is still a conversion of /img into /app/webroot/img. I've done what you've said in the edit (its the code I now have on my question above), the folder is still accessible. – dot Jun 26 '12 at 13:20
  • Where is `img` folder physically? in `/var/www/img` ? or in `/var/www/app/webroot/img` ? – poncha Jun 26 '12 at 13:24
  • I'm using wamp, and storing a cakephp project inside its www folder. The img folder is in app/webroot/img (or www/app/webroot/img) and is accessible by say 192.168.1.2/img (with 192.168.1.2/ loading the index page), which is rewritten into 192.168.1.2/app/webroot/img on the browser url – Bimp Jun 26 '12 at 13:29
  • then you need to add `app/webroot/` in RewriteCond (before `img/`) – poncha Jun 26 '12 at 13:30
  • But I've already included it on the 2nd line of RewriteCond (as above on my question). Is it not supposed to go there? – dot Jun 26 '12 at 13:33
  • @nepo see `EDIT2`. moved your original rules up, merged them into one, and added `RewriteCond` that does not let the rules loop – poncha Jun 26 '12 at 13:40
  • But this makes 192.168.1.2 (my index) lead to 192.168.1.2/app/webroot, and img folder still accessible – dot Jun 26 '12 at 13:46
  • I'm sorry, I was editing the wrong htaccess file. I edited the one inside webroot folder and now the images aren't loading. However, is there a way to make the images load inside the html code, just not viewable by direct link? – dot Jun 26 '12 at 13:50
  • @nepo : try to browse http://poncha.net/img or http://poncha.net/ or http://poncha.net/app/webroot/img ... (yes, i destroyed my homepage for you lol ;) ) - i used the same ruleset that i poseted in `EDIT2` there – poncha Jun 26 '12 at 13:52
  • Sorry to put you in all this trouble, see above please. – dot Jun 26 '12 at 13:53
  • This should be exactly what it does... refresh http://poncha.net/app/webroot/ - there should be a file 'images.html' there. if you go into `img/` yourself, it wont let you, but if you open that file and click on a link - you will see that the url goes into img/ – poncha Jun 26 '12 at 13:55
  • I was talking more in the sense of displaying images inside my html, which at the moment, doesn't seem to be working, for example my index is missing the logo which is stored inside the img/ folder. – dot Jun 26 '12 at 13:57
  • @nepo Hm... try http://poncha.net/app/webroot/img/seraph_90x90.jpg vs http://poncha.net/app/webroot/images.html - do you see the image in html now? – poncha Jun 26 '12 at 13:59
  • I am in fact able to see the image the html. There's something awkward going on: accessing from my laptop (over lan) using the 192.168.1.2 address works as intended (images loaded inside html but no direct access) but if i use the url from my pc which has that address, the images aren't loading (but i can access just fine through localhost/). I'll probably use `RewriteCond %{HTTP_REFERER} !192.168.1.2` for now but i'm intrigued. – dot Jun 26 '12 at 14:04
  • Right, the address you compare in that RewriteCond should match the address you're accessing the site with... `Referer` http header is set by browser to a url of previous page (or in case of images in an html - it will be the url of the html containing images)... – poncha Jun 26 '12 at 14:09
  • Well yes but no matter what I put in the referer condition, html image display should be possible with all accessing addresses, shouldn't it? – dot Jun 26 '12 at 14:19
  • by the wayI can't seem to be able to access the image folder directly no matter the address I put in the RewriteCond %{HTTP_REFERER} (tried 127.0.0.1, localhost, 192.168.1.2 and accordingly tried accessing through the browser) – dot Jun 26 '12 at 15:27
  • That may be due to `Options -Indexes` (which is the default) which restricts directory listings anyway – poncha Jun 26 '12 at 15:47
  • just to be clear, should the `http_referer` allow me to have _completely free_ access to image folder through, say, localhost/img, or only through ways like the html page you linked above, as in _only_ through a link (which means other computers can have access to it as long as they have the right to view the page)? – dot Jun 26 '12 at 16:16
  • It should allow you complete access (via link or img src) to any *file* inside, but the directory index has other limitation (not just this rewrite rule), thats why you don't see this. if you want to remove the limitation for the directory index, add `Options +Indexes` in .htaccess (enough to put it into .htaccess inside img folder itself) – poncha Jun 26 '12 at 16:19
  • Hmm, I don't seem to have direct access to files or folders at all. Edited the htaccess code on my question with the correct code of the webroot htaccess file, `index.php` being the default index.php placed in webroot that cakephp uses. – dot Jun 26 '12 at 16:45
  • if you're inside webroot, then the htaccess shouldnt state `app/webroot` in the rules... – poncha Jun 26 '12 at 16:55
  • are you talking about the "avoiding rewrite rules" part? So it should change into something like `RewriteCond %{REQUEST_URI} !^/ RewriteRule (.*) $1 [L,R]` ? Because what I have right now with the app/webroot included does the job of preventing direct linking sort of correctly. – dot Jun 26 '12 at 17:22
  • Wait, you did say `via link or img src` above. does this mean that direct linking through url in the browser is prohibited from all sources? (As in just launching my browser and typing localhost/img) – dot Jun 26 '12 at 17:33
  • link or img src *only from within the site* ;) i should've mentioned that ;))) – poncha Jun 26 '12 at 17:39
  • yes, it is prohibited from bookmarking. because when you launch a browser pointing directly to this url - then it does not send any referer (there is not "previous page") – poncha Jun 26 '12 at 17:40
  • So if i loaded index to have a "correct" referer, and then did page.com/img I should have access, no matter who I am? This isn't what I would want. What I want (and what is currently happening) is that noone can see (through browser url's) images unless they're loaded inside the actual page. – dot Jun 26 '12 at 17:47
  • nope, if you edit the url manually in the browser url bar - it won't let you in. only if index.html (or other page in your site) links to it specifically – poncha Jun 26 '12 at 17:47
  • Ok, so it _is_ working as intended, I didn't just _randomly_ have this result. But I'm still not sure about the app/webroot part you told me to remove. I understand that its strange for it to be there, but with or without it it works the same, and I'm not sure what I need to remove exactly (mostly which `/`'s i'm supposed to leave behind) – dot Jun 26 '12 at 17:52