Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

How to Protect Uploads, if User is not Logged In ? WordPress

  • SOLVED

Hi,

I use WP multisite.
All subsites are protected by the plugin "userpro" : https://codecanyon.net/item/userpro-user-profiles-with-social-login/5958681
You must be logged in to access the sites.

Problem : the folder "wp-content/uploads" and its files are accessible to all users, connected and no-connected.

How can I protect the access to "uploads" ? How to Protect Uploads, if User is not Logged In ?

I have try this solution : https://wordpress.stackexchange.com/questions/37144/how-to-protect-uploads-if-user-is-not-logged-in/37743#37743
That doesn't work. (maybe because I use a wp multisite)

I have try this solution : https://www.mojowill.com/developer/secure-your-gravity-forms-uploads/
That doesn't work.

Thanks :))

Answers (6)

2017-06-15

Reigel Gallarde answers:

here's what I found out... dl-file.php on your links are working.

what's not working is your .htaccess.. the sample given are not written for multisite...

here are my files.
dl-file.php
https://gist.github.com/reigelgallarde/699ac4abd2edbc310e33f87150478d0e
.htaccess
https://gist.github.com/reigelgallarde/d531f07815f30c52993ac110b3684dd3

I modified these lines

#Upload Protection
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/([_0-9a-zA-Z-]+/)([_0-9a-zA-Z-]+/)(.*)$ dl-file.php?file=$3 [QSA,L]

and should be added after
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

this is because, if you put it at the bottom, it will not be reach because there are already rules set matched...

check demo here: http://demo.reigelgallarde.me/ppqp/product/ship-your-idea-2/
images will not be served...
login using demo/demo to test logged in user


Reigel Gallarde comments:

I'm about to sleep, I will remove demo user now....
You can test it on your site...
Please don't copy my .htaccess... it might not work on your website...
just copy those 2 lines...


Sébastien | French WordpressDesigner comments:

that sounds good but there is a problem with this lines :
require_once('wp-load.php');
is_user_logged_in() || auth_redirect();
$upload_dir = wp_upload_dir();
$basedir = $upload_dir[ 'basedir' ] . '/';

$file = rtrim( $basedir, '/' ) . '/' . str_replace( '..', '', isset( $_GET[ 'file' ] ) ? $_GET[ 'file' ] : '' );
if ( ! $basedir || ! is_file( $file ) ) {
status_header( 404 );
die( '404 — IN THIS FILE : dl-file.php ' . $file );
}


when I am logged in one image is not displayed, it url is :
http://mysite.com/wp-content/uploads/2015/08/sable-1.jpg
at this url, a blank page is displayed with this message :
404 — IN THIS FILE : dl-file.php /home/mysite/www/wp-content/uploads/sable-1.jpg

As you can see the url displayed is not correct.

wp-content/uploads/sable-1.jpg
instead of
wp-content/uploads/2015/08/sable-1.jpg


Reigel Gallarde comments:

are testing it on a multisite? I modified the code of .htaccess to work with multisite... it will not work on non multisite
on a non multisite, the .htaccess on the links you provided should work.


Reigel Gallarde comments:

^wp-content/uploads/([_0-9a-zA-Z-]+/)([_0-9a-zA-Z-]+/)(.*)$ dl-file.php?file=$3 [QSA,L] will match something like http://mysite.com/wp-content/uploads/sites/8/2015/08/sable-1.jpg
note of the sites/8
this is what my multisite is setup... the default setup..

on the links you provided they have this
^wp-content/uploads/(.*)$ dl-file.php?file=$1 [QSA,L]
which can match http://mysite.com/wp-content/uploads/2015/08/sable-1.jpg


Sébastien | French WordpressDesigner comments:

testing on a multisite of course
the image is on the homepage of the main site

I have no understand your explanation. What must i do ?


Reigel Gallarde comments:

ok... lets try this..

use my htaccess
https://gist.github.com/reigelgallarde/d531f07815f30c52993ac110b3684dd3
but replace
^wp-content/uploads/([_0-9a-zA-Z-]+/)([_0-9a-zA-Z-]+/)(.*)$ dl-file.php?file=$3 [QSA,L]
replace that with
^wp-content/uploads/(.*)$ dl-file.php?file=$1 [QSA,L]

let me know if this works.


Sébastien | French WordpressDesigner comments:

same problem (image not displayed) but now the url of the image redirect to wp-login.php


Reigel Gallarde comments:

what do you get if image not display?


Reigel Gallarde comments:

I mean when you visit an image url then logged in, what do you get with the image url visited?


Sébastien | French WordpressDesigner comments:

the image is here : http://superpositif.com/
the homepage is not protected, you don't need to be connected to visit this page


Reigel Gallarde comments:

but the image is not on uploads folder
http://superpositif.com/wp-content/themes/sentric/images/logo.png


Reigel Gallarde comments:

sorry, I only see this... attached is a screenshot


Sébastien | French WordpressDesigner comments:

yes the image is between "sentric" and the button "acces interne cil.not" but it's not displayed
you can right-clic to open it


Sébastien | French WordpressDesigner comments:

this is the url of the image :
http://superpositif.com/wp-content/uploads/2015/08/sable-1.jpg


Reigel Gallarde comments:

It's asking me to logged in, is this not right?


Sébastien | French WordpressDesigner comments:

I need protect files in uploads folder on the protected page, but this homepage is not protected :)
The homepage is accessible for non logged in users


Sébastien | French WordpressDesigner comments:

I can use an image which is not in "uploads" folder for this homepage, but is it not possible to restrict the access to "uploads" folder only on the protected pages ?


Sébastien | French WordpressDesigner comments:

I can use an image which is not in "uploads" folder for this homepage, but is it not possible to restrict
the access to "uploads" folder only on the protected pages ?


Reigel Gallarde comments:

wait... are you saying it's now working on the protected page, but you don't want it on the home page?


Reigel Gallarde comments:

if you're going to protect uploads folder, all images from that folder and sub folder will be protected.. no matter where the image is is called....

I suggest you use another folder for your home page or for your protected page images... and then protect only that folder for the protected pages...


Sébastien | French WordpressDesigner comments:

Results of my tests : in fact, the first solution works fine.
The image in the homepage is not displayed but I use an image located in the theme folder instead of this one.

So I use this dl-file.php : https://gist.github.com/reigelgallarde/699ac4abd2edbc310e33f87150478d0e
And this htaccess

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

#Upload Protection
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/([_0-9a-zA-Z-]+/)([_0-9a-zA-Z-]+/)(.*)$ dl-file.php?file=$3 [QSA,L]

# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]


I have just a problem : my site is now very very very slow !!
Try to go to the home and clic on a button.

I think that it's because several script are in the "uploads" folder.
Is it possible to restrict the access only for the .doc, .docx, .pdf and not for images and .js script ?


Reigel Gallarde comments:

you can change this line in htaccess

RewriteRule ^wp-content/uploads/([_0-9a-zA-Z-]+/)([_0-9a-zA-Z-]+/)(.*)$ dl-file.php?file=$3 [QSA,L]

to

RewriteRule ^wp-content/uploads/([_0-9a-zA-Z-]+/)([_0-9a-zA-Z-]+/)(.*\.(doc|docx|pdf))$ dl-file.php?file=$3 [QSA,L]


Reigel Gallarde comments:

this will put restriction on files .doc, .docx, .pdf.

you can add more file types in this line (doc|docx|pdf)
example adding jpg, (doc|docx|pdf|jpg)


Reigel Gallarde comments:

I've research more and found out that you can create .htaccess to any folder, and it will only affect that folder...

so, this might help in your problem of website slowing down.
you can put back the old .htaccess and we can create another .htaccess in your uploads folder that has this rule:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule (\.(doc|docx|pdf))$ ../../dl-file.php?file=$1 [QSA,L]
</IfModule>


not sure if this will really help though, because I'm not experiencing any slowdown on my website.


Reigel Gallarde comments:

error typo

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule (.*\.(doc|docx|pdf))$ ../../dl-file.php?file=$1 [QSA,L]
</IfModule>


Sébastien | French WordpressDesigner comments:

that seems ok... but no :
when I am connected, if I try to open a link to a docx located in "uploads" folder, I have a 404 error
with the message :
"404 from dl-file.php — File not found./home/superpos/www/wp-content/uploads/sites/2/sites/2/2015/08/my-document.docx"

("404 from dl-file.php" is the message I have write in dl-file.php)


Reigel Gallarde comments:

ok... which .htaccess is causing that? are you doing my last suggestion?
I need to know, something is off with the code... it seems it duplicated sites/2/


Reigel Gallarde comments:

can you try this .htaccess on your uploads folder...

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule \.(doc|docx|pdf)$ dl-file.php?file=$1 [QSA,L]
</IfModule>


and with that you should remove this lines on the .htaccess of your root folder of WordPress
#Upload Protection
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/([_0-9a-zA-Z-]+/)([_0-9a-zA-Z-]+/)(.*)$ dl-file.php?file=$3 [QSA,L]


Reigel Gallarde comments:

oh wait... wrong copy paste... sorry...

this is the .htaccess that should go to uploads folder

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ([_0-9a-zA-Z-]+/)([_0-9a-zA-Z-]+/)((.*)\.(doc|docx|pdf|jpg))$ dl-file.php?file=$3 [QSA,L]
</IfModule>


Reigel Gallarde comments:

remove jpg in here (doc|docx|pdf|jpg) if you don't need to restrict images...


Sébastien | French WordpressDesigner comments:

Your last code doesn't work but there is a mistake in your code
You write
dl-file.php
instead of
../../dl-file.php

When I modify that seems ok :)


Reigel Gallarde comments:

and yet another thing I forgot... haha glad that you found it and got it working...

2017-06-15

Jayaram Y answers:

Have you tried this : https://wordpress.stackexchange.com/questions/63410/how-to-protect-uploads-in-multisite-if-user-is-not-logged-in


Sébastien | French WordpressDesigner comments:

Thanks.
I just try, it does not work unfortunately.


Sébastien | French WordpressDesigner comments:

1-
if I use this dl-files.php : https://wordpress.stackexchange.com/questions/63410/how-to-protect-uploads-in-multisite-if-user-is-not-logged-in
and this htaccess
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/(.*)$ dl-files.php?file=$1 [QSA,L]


dl-files.php redirect user in 403 when user is not loggued and try to access uploads
if user is loggued in, there is a 404
-> not good. If I am loggued in, why there is a 404 ??

2-
if I use this same dl-files.php
and this htaccess
RewriteRule ^files/(.+) dl-files.php?file=$1 [L]
I can open the file when I am logged in or not logged in


Sébastien | French WordpressDesigner comments:

for information, the content of my htaccess is :
[code]RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L][/code]


Sébastien | French WordpressDesigner comments:

for information, the content of my htaccess is :
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]

2017-06-15

Jeremy answers:

When you say protect your Uploads from users who are not logged in, what do you mean exactly? How are logged in users using uploads differently?


Sébastien | French WordpressDesigner comments:

Users are connected in front-end, via the plugin "userpro".
For this logged users, there aure some links to download files (docx).

I need to protect this links and this files from users who are not logged in.

Do you understand ?


Sébastien | French WordpressDesigner comments:

1-
if I use this dl-files.php : https://wordpress.stackexchange.com/questions/63410/how-to-protect-uploads-in-multisite-if-user-is-not-logged-in
and this htaccess
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/(.*)$ dl-files.php?file=$1 [QSA,L]


dl-files.php redirect user in 403 when user is not loggued and try to access uploads
if user is loggued in, there is a 404
-> not good. If I am loggued in, why there is a 404 ??

2-
if I use this same dl-files.php
and this htaccess
RewriteRule ^files/(.+) dl-files.php?file=$1 [L]
I can open the file when I am logged in or not logged in


Sébastien | French WordpressDesigner comments:

for information, the content of my htaccess is :
`RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]`


Sébastien | French WordpressDesigner comments:

for information, the content of my htaccess is :
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]

2017-06-15

Luis Abarca answers:

Create the file dl-file.php with the content https://gist.github.com/hakre/1552239 or download it https://gist.github.com/hakre/1552239/archive/b8d06cecc5a116de9f6cdcd4a223869f1f522560.zip

Then add this to your .htaccess file

# uploaded files
# RewriteRule ^files/(.+) wp-includes/ms-files.php?file=$1 [L]
RewriteRule ^wp-content/uploads/(.*)$ dl-file.php?file=$1 [QSA,L]


Sébastien | French WordpressDesigner comments:

I thik you have not red my question entirely.
I have write :
I have try this solution : https://wordpress.stackexchange.com/questions/37144/how-to-protect-uploads-if-user-is-not-logged-in/37743#37743
That doesn't work. (maybe because I use a wp multisite)


Sébastien | French WordpressDesigner comments:

1-
if I use this dl-files.php : https://wordpress.stackexchange.com/questions/63410/how-to-protect-uploads-in-multisite-if-user-is-not-logged-in
and this htaccess
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/(.*)$ dl-files.php?file=$1 [QSA,L]


dl-files.php redirect user in 403 when user is not loggued and try to access uploads
if user is loggued in, there is a 404
-> not good. If I am loggued in, why there is a 404 ??

2-
if I use this same dl-files.php
and this htaccess
RewriteRule ^files/(.+) dl-files.php?file=$1 [L]
I can open the file when I am logged in or not logged in


Sébastien | French WordpressDesigner comments:

for information, the content of my htaccess is :


RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]

2017-06-15

Cesar Contreras answers:

Use this file https://goo.gl/lMVu5t
and change the contents of your .htaccess by this:

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/([_0-9a-zA-Z-]+/)([_0-9a-zA-Z-]+/)(.*)$ dl-file.php?file=$3 [QSA,L]
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]


Sébastien | French WordpressDesigner comments:

read the comment I have post to Reigel Gallarde.
There is the same problem with your code :-/


there is a problem with this lines :
require_once('wp-load.php');
is_user_logged_in() || auth_redirect();
$upload_dir = wp_upload_dir();
$basedir = $upload_dir[ 'basedir' ] . '/';

$file = rtrim( $basedir, '/' ) . '/' . str_replace( '..', '', isset( $_GET[ 'file' ] ) ? $_GET[ 'file' ] : '' );
if ( ! $basedir || ! is_file( $file ) ) {
status_header( 404 );
die( '404 &#8212; IN THIS FILE : dl-file.php ' . $file );
}



when I am logged in one image is not displayed, it url is :
http://mysite.com/wp-content/uploads/2015/08/sable-1.jpg
at this url, a blank page is displayed with this message :
404 — IN THIS FILE : dl-file.php /home/mysite/www/wp-content/uploads/sable-1.jpg

As you can see the url displayed is not correct.

wp-content/uploads/sable-1.jpg
instead of
wp-content/uploads/2015/08/sable-1.jpg


Reigel Gallarde comments:

are testing it on a multisite? I modified the code of .htaccess to work with multisite... it will not work on non multisite


Sébastien | French WordpressDesigner comments:

testing on a multisite of course
the image is on the homepage of the main site

2017-06-15

Rempty answers:

Can you edit the file wp-includes/ms-files.php
And after this line
if ( !is_multisite() )
die( 'Multisite support not enabled' );

Add
if(!is_user_logged_in()){
status_header(403);
die('403 &#8212; Forbidden');
}

please test if this restrict the files to logged in users


Sébastien | French WordpressDesigner comments:

No, that doesn't work. This doesn't restrict the files to logged in users
Same result with this code
if( ! is_user_logged_in() )
{
wp_redirect( home_url( '/wp-login.php' ), 302 );
exit();
}



and this code
if( ! is_user_logged_in() || ! auth_redirect() )
{
wp_redirect( home_url( '/wp-login.php' ), 302 );
exit();
}