I have a very specific use case where the site built for a lawyer and each of his clients can login to their own ‘specific page/portal’ (custom post type) without the ability to access wp-admin etc. (I created all the login/register/profile-editing pages in the front end). In this page/portal the lawyer will leave messages and files for the client to download, now theoretically speaking, one client can guess (or if has knowledge of another client’s files) other file names and download then thus creating an issue with privacy/security/confidential material etc.
I’m looking for ideas/concepts for a solution, my initial thought was to have the download link point to some download.php sending the attachment id, user id, page/portal id and nonce and the on the other end processing that..
what do you think? am I on the right track or this approach is flawed?
Thanks!
What needs to happen is that you need to proxy download requests for the file types you want through WordPress. Let’s assume you’re going to restrict access to “.doc” files.
1. Define a query variable that indicates the requested file
2. Update .htaccess to forward requests for restricted files to WordPress
This will capture requests to the files you want to restrict and send them back to WordPress using the custom query variable above. Insert the following rule before the
RewriteCond
lines.3. Capture the requested file name in custom query variable; and verify access to the file:
NB This solution works for single-site installs only! This is because WordPress MU already forwards uploaded file requests in sub-sites through
wp-includes/ms-files.php
. There is a solution for WordPress MU as well, but it’s a bit more involved.I’ve recently had a related problem and wrote this article about it.
I’ll assume that the downloads are uploaded via WordPress’ media handling – or otherwise you have an attachment ID for the download.
Outline of solution
.htaccess
to block any attempt to directly access of files in uploads directory (or a sub-directory thereof) – e.g. viamysite.com/wp-content/uploads/conf/2012/09/myconfidentialfile.pdf
)Caveats
.htaccess
to provide security. If this isn’t available / turned on (nginx servers for example), then you won’t get much security. You can prevent the user browsing the uplods directory. But direct access will work.Blocking direct access
To do this in your uploads folder (or a subfolder – all confidential material must reside, at any depth, inside this folder). Place a
.htaccess
file with the following:In the following I’m assuming that you’ll be attaching confidential material to post type ‘client’. Any media uploaded on on the client-edit page will be stored in the
uploads/conf/
folderThe function to setup the protected uploads directory
Uploading confidential material
Having done that, uploaded content should be inside
uploads/conf
and trying to access it directly using your browser should not work.Downloading Content
This is easy. The download url can be something
www.site.com?wpse26342download=5
(where 5 is the attachment ID of the uploaded content). We use this to identify the attachment, check permissions of the current user and allow them to download.First, set up the query variable
Now set up a listener to (maybe) trigger the download…
Final comments
The code above may contain bugs/syntax errors and is untested, and you use it at your own risk :).
The download url can be ‘prettified’ using rewrites. As stated in the comments you can add an blank
index.php
inside every child of the protected folder to prevent browsing – but this should be prevented by the.htaccess
rules anyway.A more secure method would be to store the public files outside of a public directory. Or on an external service like Amazon S3. For the latter you’ll need to generate a valid url to fetch the file from Amazon (using your private key). Both of these require a certain level of trust in your Host / third party service.
I would be wary about using any plug-ins that suggest they offer ‘protected downloads’. I’ve not found any that provide good enough security. Please not the caveats of this solution too – and I’d welcome any suggestions or criticisms.
Probably, you might have known this trick, This code will check for current logged in user’s username and if it match it will show download link to that file, else it won’t show anything.
here is the code :
However, this will not be a good approach, as files are stored on servers, anyone with link can download that file.
I presume this information is confidential and therefore in addition to hiding the links to the files you’ll want to actually make them inaccessible completely to anyone on the web, even if they were to guess the URL, unless that user has explicit permission to download the files.
Look into storing the files on Amazon S3 securely and then providing pre signed (time limited) URLs to the file provided the correct security checks have been satisfied (i.e. the user has logged into your site and is who they say they are).
There is a very good AWS SDK that makes it very straight forward to do this.
What you’ll need to research is how to send files uploaded through the WP upload interface into S3 instead, alternatively build your own uploader.
Another options would be too look into the code of WP e-commerce. They offer secure download of software files (e.g. MP3s). I believe the files are converted into hashes with an encryption key that is generated per user on purchase. This would take a some deciphering to see how it worked, but the process will not be unique to this plugin so other examples will be available (somewhere).
I think encryption of the files is the way to go like the above answer.
There is a plugin on WordPress.org that lets you protect the downloads.
http://wordpress.org/extend/plugins/download-protect/
You could use amazons service or google drive as well. There are lots of services offering protected downloads such as drop box too.