开发者

PHP Session Synchronisation

I am developing a WebApp in PHP. The user will be able to click a button and the PHP code will end up calling a system exec. Since the WebApp will be using AJAX, there is the possibility that the user could click the button twice, or indeed click another button which would start another exec process.

Now, I know that I could write a little javascript that would disable the buttons until the single event has been completed. However, this is client side enforcement, which can easily been overwritten.

Is there somethig I could do on the PHP side to stop things like this happening? In my head, I have an idea of having a session variable act as a "semaphore" and before every script is executed, this variable would be c开发者_如何学运维hecked and must return 0 before the script could continue.

Am I going about that the right way? Or does that just open a can of worms for deadlocks/race conditions?

Thanks

Update: Just to put it into context, the system I'm developing will be used to start, stop, and reimage Virtual Private Servers. If the reimaging button was pressed, the PHP script will call some bash script to start to re-image the VPSes. However if a user tried to start the VPS while this was being done....


You could use jQuery.ajax() and set the option async to false:

async Default: true By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active

You could use it like this:

$.ajax({
    type: "POST",
    url: "file.php",
    async: false,
    data: data,
    success: function(return){
        alert("Success: "+return);
    }
});

If you want to add a loader just apply it as:

startLoader();
$.ajax({
    type: "POST",
    url: "file.php",
    async: false,
    data: data,
    success: function(return){
        alert("Success: "+return);
    }
});
endLoader();

However you PHP idea is simply not a good one. Opening a session and do all the process for this kind of thing is just useless and slow your script down. You should be asking yourself: Do I really need to block this?

If the answer is yes then do this: Create a table called processes in you database. Inside that table create 2 fields: One will be the process identifier: process_id; the second will be the process status: process_status. The first is an integer you will define with sha1(IMAGE). The second will be an integer: 1 for "busy", 0 for "free".

Then you could do something like this:

SELECT process_status FROM vps_processes WHERE process_id = sha1(CURRENT_IMAGE);

And check whatever it is 1 or 0. If it is 1 then block the script; If it is 0 then you query:

UPDATE vps_processes SET process_status = 1 WHERE process_id = sha1(CURRENT_IMAGE);

then run what you have to run and at the end of the script query:

UPDATE vps_processes SET process_status = 0 WHERE process_id = sha1(CURRENT_IMAGE);


The fact that you want it to be a server-side solution makes me suspect that you don't trust the user here. Then you obviously can't use the session structure since that's also possible to circumvent by the client. Instead, you'll have to lock the single IP address or some similar approach. Maybe have a folder with lock files, where you create a file named after the IP performing the request.


Unless you want to enforce the per-user limit between different machines, you could always use http://php.net/manual/en/function.flock.php to lock the operation on a file called lock.$username

Alternatively, you could simply not care about enforcing the limit, since there are only limited number of php processes that are going to run at the same time anyways.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜