Kristoff1875 Posted June 9, 2014 Share Posted June 9, 2014 I'm storing website files online and each user can upload their own files and admin can upload files for that user specifically. How would I go about making sure nobody else can download their PDF file? Would it be a case of assigning a folder for each user's documents and not allowing access to any other user to that folder? Thanks in advance. Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/ Share on other sites More sharing options...
JonnoTheDev Posted June 9, 2014 Share Posted June 9, 2014 (edited) If you have users then you need to authenticate a user before they are allowed to upload or download a file. i.e. They need to login to the website. If your users are stored in a database table then each user will have an id (primary key). Store the uploaded filenames in a database table along with the id of the user who uploaded them. A user should only be allowed to download their own files. i.e. If my user id is 123 I can only download files where user_id = 123 Simple database schema user ====== user_id name username password user_file ======= file_id user_id filename You only need to split the folders up if you are going to have thousands of files uploaded otherwise just upload the files to a folder that it outside of the website document root. Edited June 9, 2014 by neil.johnson Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482287 Share on other sites More sharing options...
Kristoff1875 Posted June 9, 2014 Author Share Posted June 9, 2014 I've gone about it slightly differently, how secure does this sound? I'm using the document name, along with their UserID and Salt to generate a hashed file name for the file. I'm then running a script that is decoding that using the session username and document ID they clicked through from to download the file. Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482312 Share on other sites More sharing options...
jazzman1 Posted June 9, 2014 Share Posted June 9, 2014 Sounds like you need to find a simple file manager written in php/js/html. Neil is already described the basic skeleton, but dealing with users/dirs/files/permmissions and so forth on the web server ( where the users not belong to the file server) is not an easy job as you think. Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482328 Share on other sites More sharing options...
Kristoff1875 Posted June 9, 2014 Author Share Posted June 9, 2014 Would the way i've done it not be secure enough? It works for only being able to load your own files from early testing that i've done. Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482329 Share on other sites More sharing options...
jazzman1 Posted June 9, 2014 Share Posted June 9, 2014 Is it only one uploaded/downloaded directory for all users? Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482330 Share on other sites More sharing options...
Psycho Posted June 9, 2014 Share Posted June 9, 2014 If you believe that obfuscation is a form of security, then yes what you propose would work. (Hint: obfuscation is not the same as security). How would I go about making sure nobody else can download their PDF file? If you want to be sure no one but the authorized user can download the files then you need to first put the files into a directory that is not web accessible. Then, you would put a process in place to provide an authentication mechanism (as described above) when either displaying the list of files or when attempting to "download". The download process would be implemented by passing an id to a download page. The download page would use the ID to find the file (typically stored in a DB) and send it to the user directly. Here is what the directory structure might look like | |-[my_website_root] | | | |-[images] | |-[style_sheets] | |-[pages] | |-[files_for_download] Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482334 Share on other sites More sharing options...
jazzman1 Posted June 9, 2014 Share Posted June 9, 2014 (edited) If you believe that obfuscation is a form of security I think he renames the uploaded file using a hash algorithm as a file name, then just compare if this name exists in the db table and belongs to the uploader (user) with this ID. Well, this would work good, but could cause a lot of server's resources Edited June 9, 2014 by jazzman1 Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482337 Share on other sites More sharing options...
Kristoff1875 Posted June 9, 2014 Author Share Posted June 9, 2014 (edited) Well I have a page called show-docs.php and that loads all of the docs from the database for that user, each document has a hashedID which is generated using a second (different from the password one) salt, called UpSalt. When uploading the file, the hashedID is generated and stored in the documents table along with the UserID. When a user is on show-docs.php and they click one of the items in the list, the page then grabs that user's UpSalt, and uses their session ID to identify the correct file in the documents folder. The thinking behind this is that each document when uploaded will have it's own unique generated filename and that is simply matched up when trying to download it. I'm actually thinking now that it would be a good idea to run a small query to check the document stored in the database belongs to the current user in the session, that wouldn't take up much resources would it? So far in my tests that is working fine, but as Psycho says, the files aren't secure, just hidden... Could you guys point me in the direction of making the directory unaccessible? Edit: Psycho, you posted this: | |-[my_website_root] | | | |-[images] | |-[style_sheets] | |-[pages] | |-[files_for_download]Which i'm not too sure I understand currently... I have the following: | |-[my_website_root] | |-[css] |-[documents] |-[images] Edited June 9, 2014 by Kristoff1875 Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482342 Share on other sites More sharing options...
jazzman1 Posted June 9, 2014 Share Posted June 9, 2014 Well, in this case instead of build a new layer of security based on the web server (most likely a shared hosting) for multiple users, I'd be consider to use the database as an upload storage. Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482350 Share on other sites More sharing options...
Psycho Posted June 10, 2014 Share Posted June 10, 2014 (edited) Psycho, you posted this: | |-[my_website_root] | | | |-[images] | |-[style_sheets] | |-[pages] | |-[files_for_download] Which i'm not too sure I understand currently... I have the following: | |-[my_website_root] | |-[css] |-[documents] |-[images] I'm pretty sure that is not your directory structure. If it was, then users would not be able to load images or CSS files. All those folders must be in a parent folder that is your actual root. Using my previous example: | |-[my_website_root] | | | |-[images] | |-[style_sheets] | |-[pages] | |-[files_for_download] You would need to configure, on your web host, to point your domain to the [my_website_root] folder. I.e. when a user enters www.mysite.com it points to the [my_website_root] folder. It is impossible for a user to enter a URL to directly access any of the files because they are not publicly available. As for your current approach, I think the logic is more complicated than it needs to be. You already have to authenticate the user, correct? Then there is no need, in my opinion, to use some sort of hash on the file name as part of the security. Instead, you can have database details to determine who can access which files. If all files have one, and only one, user with rights to access the file. Then you can have a column in the files table with the user ID who has rights to the file (you can implement logic that an 'admin' can access any files). Then, when a request is made to a file, you would verify that the logged in user has rights to the file before providing it to them. How you provide the file to them, since it is not publicly accessible, is through a force-download script which will 'read' the file from the file system folder that is accessible on the server, but not from the user, and output to the user. Here is an example of a force download script: http://davidwalsh.name/php-force-download Edited June 10, 2014 by Psycho Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482393 Share on other sites More sharing options...
Kristoff1875 Posted June 10, 2014 Author Share Posted June 10, 2014 Sorry, you're right, I completely read your structure wrong, it's currently like this: | |-[my_website_root] | | | |-[css] | | |-[images] | |-[documents] So if I understand correctly, on the server I need to put the files in / instead of /www ? I currently download the file using: if (!isset($_SESSION['UserID'])) { echo 'None'; exit; } $file = '../documents/'.$hashedID.'.'.$FileType; if (file_exists($file)) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($file)); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($file)); ob_clean(); flush(); readfile($file); exit; } else { echo 'error'; } I know I need to change the path for the documents in that, but basically if I add a database query (select where documentID = documentID where userID = Session[userID] for example) then that should be fairly secure? Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482400 Share on other sites More sharing options...
Kristoff1875 Posted June 10, 2014 Author Share Posted June 10, 2014 Well, in this case instead of build a new layer of security based on the web server (most likely a shared hosting) for multiple users, I'd be consider to use the database as an upload storage. It's currently being built on shared storage, but moving to dedicated hosting due to the nature of the files to be hosted. Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482401 Share on other sites More sharing options...
Psycho Posted June 10, 2014 Share Posted June 10, 2014 Since you are reading the files and pushing them to the user rather than the user downloading them, you really don't need to additional layer of "encryption" of the file name. Just authenticate the user and verify they are allowed to view the file and push it to them. The file name hashing really adds no additional security since you would have to authenticate the user first anyway. If someone has already gotten around the authentication process as another user then the additional hashing of the filename is moot since their "UserID" would be that of the user they are impersonating. If the files are of a very sensitive nature, then you could look at securing them on the server-side from someone who gains access to the server. You could either store the files directly in the database and encrypt them there (as jazzman1 suggested) or you could encrypt the actual files and then decrypt them before sending them to the user. Of course, if you are going to go to that extent then you should be using HTTPS. Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482406 Share on other sites More sharing options...
Kristoff1875 Posted June 10, 2014 Author Share Posted June 10, 2014 I have done away with encrypting the file name now, and am checking if they are the user from the database. Which option would you suggest is best for encrypting the files? The website will be using HTTPS anyway, just not currently. Cheers Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482407 Share on other sites More sharing options...
Psycho Posted June 10, 2014 Share Posted June 10, 2014 Which option would you suggest is best for encrypting the files? Not my area of expertise. Suggest you do some research. Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482411 Share on other sites More sharing options...
jazzman1 Posted June 10, 2014 Share Posted June 10, 2014 (edited) It's currently being built on shared storage, but moving to dedicated hosting due to the nature of the files to be hosted. A lot of security technics you could apply in the dedicated server from MAC/DAC/SeLinux until chroot, LXC so forth if you're running the project on a linux server. About SSL, this is a method of encripting all TCP/IP transmissions stack (including web pages and data entered into web forms) in case some malicious user tries to sniff and catch the data trafic and tying to read or re-write the same data pretending that he is the owner of the file, most often that happened in a local environment. So HTTP over SSL is a good thing you should use it. I'm still stay behind the scenario to use the database as an upload files storage engine since the files contain a sensitive data and not to be publish at all. Edited June 10, 2014 by jazzman1 Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482413 Share on other sites More sharing options...
Kristoff1875 Posted June 11, 2014 Author Share Posted June 11, 2014 I thought it was a bad idea to store large binary data in a database? Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482449 Share on other sites More sharing options...
jazzman1 Posted June 11, 2014 Share Posted June 11, 2014 In situations where your application needs to store and share a lot of public binary files, as pics, movies, other shared data, etc.. where you expect to have multiple requests to those files and queries to your database server, I' m agree that the preffered method is to save the binary files using the server’s file system and that's considered to be the easiest and fastest way when storing files. However, you have a completely different situation here! When the data shouldn't be shared amoung people, as I said above the database application will provide you a new different level of security onto the main server-system, that means you must have an account name and password for the server administrator or for a group administrator that has the privilege to perform some actions on databases and handling those account permmisions on the files in much more easier way. Anyways.... you should get the fastest and eaysiest way for youself Quote Link to comment https://forums.phpfreaks.com/topic/289080-making-documents-only-accessible-to-specific-users/#findComment-1482468 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.