Media/Uploads restrictions

This article will help you secure your medias (any files uploaded) on WordPress. You need basic understanding of PHP and Apache to get it done. 

Note that by default, even if all your pages are restricted, any document uploaded can be accessed without any restriction, just with the URL. 

But they are not listed neither so as long as they are not shared no one will find theme. Nevertheless, it is something you might not want. 

WordPress stores any uploaded file within your wp-content/uploads/ directory. 

You can learn more about WordPress uploads here: https://codex.wordpress.org/Uploading_Files

Woffice has no impact, as a theme, on how we can restrict access to the uploads folder, as this happens a couple levels below on the server configuration. 

The following will only work for servers using Apache (and not Ngnix). 

You can learn more about Apache here: https://kinsta.com/knowledgebase/what-is-apache/

So how to restrict access to the uploads/ folder only to logged in users? 

  1. Edit your /.htaccess file and add the following lines: 
RewriteCond %{REQUEST_FILENAME} -s

RewriteRule ^wp-content/uploads/(.*)$ uploads-check.php?file=$1 [QSA,L]

2. Upload a uploads-check.php file with the following content inside: 

<?php

/*

 * uploads-check.php

 *

 * Protect uploaded files with login.

 *

 * @link http://wordpress.stackexchange.com/questions/37144/protect-wordpress-uploads-if-user-is-not-logged-in

 *

 * @author hakre <http://hakre.wordpress.com/>

 * @license GPL-3.0+

 * @registry SPDX

 */

require_once('wp-load.php');

is_user_logged_in() ||  auth_redirect();

list($basedir) = array_values(array_intersect_key(wp_upload_dir(), array('basedir' => 1)))+array(NULL);

$file =  rtrim($basedir,'/').'/'.str_replace('..', '', isset($_GET[ 'file' ])?$_GET[ 'file' ]:'');

if (!$basedir || !is_file($file)) {

    status_header(404);

    die('404 — File not found.');

}

$mime = wp_check_filetype($file);

if( false === $mime[ 'type' ] && function_exists( 'mime_content_type' ) )

    $mime[ 'type' ] = mime_content_type( $file );

if( $mime[ 'type' ] )

    $mimetype = $mime[ 'type' ];

else

    $mimetype = 'image/' . substr( $file, strrpos( $file, '.' ) + 1 );

header( 'Content-Type: ' . $mimetype ); // always send this

if ( false === strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS' ) )

    header( 'Content-Length: ' . filesize( $file ) );

$last_modified = gmdate( 'D, d M Y H:i:s', filemtime( $file ) );

$etag = '"' . md5( $last_modified ) . '"';

header( "Last-Modified: $last_modified GMT" );

header( 'ETag: ' . $etag );

header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + 100000000 ) . ' GMT' );

// Support for Conditional GET

$client_etag = isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ? stripslashes( $_SERVER['HTTP_IF_NONE_MATCH'] ) : false;

if( ! isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) )

    $_SERVER['HTTP_IF_MODIFIED_SINCE'] = false;

$client_last_modified = trim( $_SERVER['HTTP_IF_MODIFIED_SINCE'] );

// If string is empty, return 0. If not, attempt to parse into a timestamp

$client_modified_timestamp = $client_last_modified ? strtotime( $client_last_modified ) : 0;

// Make a timestamp for our most recent modification...

$modified_timestamp = strtotime($last_modified);

if ( ( $client_last_modified && $client_etag )

    ? ( ( $client_modified_timestamp >= $modified_timestamp) && ( $client_etag == $etag ) )

    : ( ( $client_modified_timestamp >= $modified_timestamp) || ( $client_etag == $etag ) )

    ) {

    status_header( 304 );

    exit;

}

// If we made it this far, just serve the file

readfile( $file );

For any question, please get in touch with us on the support.