PDF files protection from external access. Accessible only to authenticated users. WordPress uploads directory PDF files protection from external access. Accessible only to authenticated users. WordPress uploads directory wordpress wordpress

PDF files protection from external access. Accessible only to authenticated users. WordPress uploads directory


The best way here is to use http://nginx.org/r/auth_request to determine, within a given location, whether the user is authenticated and access should be granted. You'd have to figure out the correct end-point for WordPress, though.

Another option is to move all the files to an http://nginx.org/r/internal location, and use X-Accel-Redirect HTTP Response Header Field from a new script handling the old location to which all the external links are made, to redirect only those clients that are authenticated to the internal location as mentioned above.


Instead of redirecting non-logged in users to error URL, pass the file path to a page - can be your home page. Add the following rule.

rewrite ^/wp-content/uploads/(.*)\.(?!js|css|png|jpe?g|gif)(.*)$ /?dwnld_file=$1.$2

Then check whether the user logged-in or not via WordPress and provide access if valid. Add the following to your theme's 'functions.php'.

//init hookadd_action( 'init', 'file_init' );function file_init() {    if ($_REQUEST[ 'dwnld_file' ] != '' ) {        if ( ! is_user_logged_in() ) { // if not logged-in            auth_redirect(); //redirect to login page            // wp_redirect( 'https://example.com/services/login-error.html' ); // or some other page            exit;        }        else {            check_download_file( $_REQUEST[ 'dwnld_file' ] ); // if logged-in pass file to download        }    }}//function to download filefunction check_download_file( $file ) {    $upload = wp_upload_dir();    $file = $upload[ 'basedir' ] . '/' . $file;    if ( !is_file( $file ) ) {        status_header( 404 );        die( 'File not found.' );    }    else {        $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' ];                    header( 'Content-type: ' . $mimetype );            $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' );            readfile( $file );            die();        }    }}

Hope this helps.


So, eventually what I found, after trying all the answers and more, was that while the site.conf #1 was working with the logged-in users for PDF files with URLs starting with https://, it was not working with previous uploads that used to have the http:// in the URL. I had to update the wp_posts table to https://example.com/wp-content/uploads/ and it was finally protecting (only) the PDF files from direct access.

Of course this is a rough workaround and keep in mind that this method will also protect PDF files that are otherwise publicly available.

Thanks for all the help.