Handle multiple PHP script calls from multiple XHR instances
Previously styled question: http://pastebin.com/cr432nLQ
I've decided to rephrase the whole question about this problem and go as thoroughly as possible. You can read the previously asked question in the paste above.
First of all, thanks to everyone for their responses, but unfortunately, they got me nowhere. I'm still in need of help for my problem.
So, I'm using a jQuery plugin named blueimp jQuery File Upload which takes care of asynchronous file uploading very nicely and it includes a lot of options. The plugin works good enough for my purposes, but there is this server side check I need to perform in order to save myself from abusive users. I'm talking about limiting the number of uploads that occur at once .
The plugin works as follows by default: User selects a number of files (or drops them to the drop zone) and each file creates a separate XHR instance which then calls my upload.php
script, which takes care of storing the files. The PHP upload script handles the XHR requests as if it was only one image, so basically, each image that requires uploading, calls the upload.php
script separately.
What I'm allowing to upload my users is images. However, I want to apply some limits to the upload count to 10 for free users and 20 for premium users. This is possible to be done via Javascript, yes, but I don't really trust Javascript for this kind of validation, hence I'm seeking a server side validation. But, how? This is quite of impossible (for me at least) to be done securely. I need to somehow make sure on my upload script that the user did not exceed the 10 (or 20) image uploads limit.
I found out that this jQuery plugin has this option named singleFileUploads
:
By default, each file of a selection is uploaded using an individual request for XHR type uploads. Set this option to false to upload file selections in one request each.
Note: Uploading multiple files with one request requires the multipart option to be set to true (the default).
true
This quite does what I need it to do - Sends an entirely filled $_FILES
array with all the submitted image uploads. But I still see a problem with this. This is still being decided by Javascript itself. Can an user modify this part of the script and set singleFileUploads
to false
again? I think they can! If they couldn't, then this question is answered right now - but I don't know.
There is an answer below that suggests the use of Apache's mod_qos
to limit the image uploads quantity, but I don't have a clue how to make it differ for the two different user types (free and premium).
Please be aware that guests are allowed to upload image as well and the free user limit should apply to them.
So what have I tried regarding all this?
I have tried creating a solution with sessions that would keep track on how much the user is uploading and for each new upload, the session's value would increment for one - A solution that was not secure enough as suggested below, since the cookies can be cleared. Beside this try, I wasn't able to apply anything from the answers below.
The question
Well, the question is quite clear since the beginning: How do I limit the number of concurrent image uploads to 10 for guests/free users and 20 to premium users securely?
EDIT: I guess it's worth mentioning that each uploaded image gets its own row in the database, with the time of the upload and name. Maybe this could help!
Thank you.
From your comment, I understand your question as : "I want to limit the number of simultaneous upload connections per client (say: max 10 simultaneous uploads per client)"
First off : I haven't looked in details at your javascript plugin, but I think it already allows that. There should at least be an option to limit the number of simultaneous requests.
[edit] found it : limitconcurrentuploads [/edit]
More generally : PHP is not the tool for the job. On the server side, the file upload (ie: the process of receiving data through an http connexion and storing it in a file on the server's drive) is handled by apache (or nginx, or whatever) before the PHP script is called. When your PHP script starts, the file is already uploaded, you cannot interrupt the transfer from inside the script.
On the server side, you should look at your php.ini / httpd.conf
options, or your apache / .htaccess
setup. php.ini
offers some options regarding File uploads (doc).
Your best go is to write this limitation in javascript, on the client side.
If you really want to bullet proof your server, you should study how you can configure your apache server to limit the number of simultaneous connections from a same IP to a given URL (I haven't found a quick, standard way to do that though).
For the last part : I found these questions on ServerFault
Apache2: Limit simultaneous requests & throttle bandwidth per IP/client? (2011)
URL-based request rate limiting in Apache (2011)
The accepted answer to the first question points to the following apache module :
mod_qos
I haven't tried it, though.
You could create an activation code (ie a random number) when generating the host page (the page issuing the xhr calls) and pass it to the script as a variable inside the page. Then you can modify your js script to pass the activation code as a get parameter to the script handling the file upload. This way you can use the activation code as the key of a db table to store and track the number of uploads executed with that code.
Note that almost everything can be manipulated over HTTP/TCP (not just sessions) so you should just ask yourself what an attacker can achieve if he/she manages to exploit your protocol.
You didn't write much about the context of this question, but if your concern is the exploitation of resources you could ask your users to open an account with your service and set a hourly/daily/weekly maximum uploaded-GBs-allowance for each account.
Hope it helps.
PS. are you sure you really need to limit the number of uploads per upload-session? Since every upload is handled separately with a separate call to the upload script, if think it could be safe to allow the user to upload as many images he wishes.
Maybe I'm not understanding your goal, but couldn't you just assign the session variable to another, reset the session variable before each loop, and make a comparison using the sum of the $_SESSION count and the "previous" count? Are you trying to prevent more than 10 aggregate uploads from each user, or just preventing 10 consecutive uploads in one go?
// Before starting your loop, assign your session variable to another.
$previously_uploaded = $_SESSION['images_session_uploaded'];
// Reset $_SESSION['images_session_uploaded'] at onset
$_SESSION['images_session_uploaded'] = 0;
// ... Do yo' thang.
// Make a comparison at the end of each loop for whatever you're checking against.
if (($_SESSION['images_session_uploaded'] + $previously_uploaded) >= MAX_FREEUSER_UPLOADS_SESSION)
{
// User has uploaded more than ten images total, but not necessarily more than ten in this round of uploads.
}
链接地址: http://www.djcxy.com/p/76768.html