今日、私は PHP が同時にリクエストを処理する方法について疑問に思っていました。PHP は複数のリクエストを同時に処理できるため、PHP スクリプトのセキュリティ ホールやバグの可能性について考えてみました。
したがって、同時に 100 件のリクエストがあり、Apache がそれらを PHP に転送するように構成されている場合です。PHPは次の例で何をしますか(このような方法で、いくつかの実世界のアプリケーションですでに見たすべての例)
すべての例は互いに類似しています。(これらの事例を解決するためのより良い方法を求めているわけではありません)
例 1: キャッシュを作成する
<?php
if (!file_exists('my_cache.txt')) {
// do something slow (taking a second or so)
file_put_contents('my_cache.txt', $cache);
}
約100件のリクエストがあると仮定します。キャッシュが100回生成され、キャッシュファイルに100回保存される可能性はありませんか?
例 2: エントリをキャッシュに書き込む
<?php
writeItemToDatabase($myItem);
if (countAllItemsInDatabase() > 100) {
$items = readAllItemsFromDatabase();
deleteAllItemsFromDatabase();
// Process items
}
「deleteAllItemsFromDatabase」関数のため、この例は少しばかげています。このスクリプトを並行して実行すると、次のことが起こります。
- 2 人のユーザーがすべてのアイテムを同時に処理する
- 一部のアイテムは処理される前に削除されるため、処理されません。
例 3: 仮想通貨
<?php
if ($user->getMoney() > 100) {
$user->decreaseMoney(100);
$user->addItem($itemToBuy);
}
スクリプトが同時に実行される可能性がある場合、この例には大きなセキュリティ上の問題があります。このアプリケーションの「購入」ボタンをすばやく押すと、ユーザー アカウントにお金が残っていなくてもアイテムを購入できる可能性があります。
質問
このような問題を防ぐためにスクリプトを書くことに少し偏執的であるか、それともこれらの例は実際の問題なのでしょうか?
そして、まれなケースですが、(これらの例のように)アクション処理されたシリアルを記述する必要がある場合、次のように、スクリプト部分を一度に1回だけ処理することを保証するPHP関数/拡張機能はありますか?
<?php
$semaphore->lock();
// Do something dangerous
$semaphore->unlock();