Skip to content

Commit

Permalink
Merge pull request #5942 from chihiro-adachi/checkout-limiter
Browse files Browse the repository at this point in the history
ShoppingControoler::checkoutでもスロットリングを実行する
  • Loading branch information
kiy0taka committed Feb 15, 2023
2 parents e29dcd2 + b39c25a commit 5f56720
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 4 deletions.
25 changes: 24 additions & 1 deletion .github/workflows/e2e-test-throttling.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
matrix:
php: [ 8.1 ]
db: [ pgsql ]
method: [ フロント画面ログイン_IP, フロント画面ログイン_会員, 管理画面ログイン_IP, 管理画面ログイン_会員, 会員登録, 問い合わせ, パスワード再発行, 非会員購入, 会員購入 ]
method: [ フロント画面ログイン_IP, フロント画面ログイン_会員, 管理画面ログイン_IP, 管理画面ログイン_会員, 会員登録, 問い合わせ, パスワード再発行, 注文確認_非会員購入, 注文確認_会員購入, 注文完了_非会員購入, 注文完了_会員購入 ]
include:
- db: pgsql
database_url: postgres://postgres:password@127.0.0.1:5432/eccube_db
Expand All @@ -47,6 +47,29 @@ jobs:
- name: Checkout
uses: actions/checkout@master

# ShoppingController::checkoutをテストするため、confirmの上限値を変更する
- name: Fix limiter limit
if: startsWith(matrix.method, '注文完了')
run: |
echo "eccube:
rate_limiter:
shopping_confirm_ip:
route: ~
limit: 1024
interval: '30 minutes'
shopping_confirm_customer:
route: ~
limit: 1024
interval: '30 minutes'
shopping_checkout_ip:
route: ~
limit: 25
interval: '30 minutes'
shopping_checkout_customer:
route: ~
limit: 10
interval: '30 minutes'" > app/config/eccube/packages/prod/eccube_rate_limiter.yaml
- name: Setup PHP
uses: nanasess/setup-php@master
with:
Expand Down
8 changes: 8 additions & 0 deletions app/config/eccube/packages/eccube_rate_limiter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,11 @@ eccube:
route: ~
limit: 1024
interval: '30 minutes'
shopping_checkout_ip:
route: ~
limit: 1024
interval: '30 minutes'
shopping_checkout_customer:
route: ~
limit: 1024
interval: '30 minutes'
8 changes: 8 additions & 0 deletions app/config/eccube/packages/prod/eccube_rate_limiter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,11 @@ eccube:
route: ~
limit: 10
interval: '30 minutes'
shopping_checkout_ip:
route: ~
limit: 25
interval: '30 minutes'
shopping_checkout_customer:
route: ~
limit: 10
interval: '30 minutes'
88 changes: 86 additions & 2 deletions codeception/acceptance/EF09ThrottlingCest.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public function パスワード再発行(AcceptanceTester $I)
$I->see('試行回数の上限を超過しました。しばらくお待ちいただき、再度お試しください。', 'p.ec-reportDescription');
}

public function 非会員購入(AcceptanceTester $I)
public function 注文確認_非会員購入(AcceptanceTester $I)
{
$I->wantTo('EF0901-UC01-T08_非会員購入');

Expand Down Expand Up @@ -265,7 +265,7 @@ private function inputGuestInfo(ShoppingNonmemberPage $page)
return $page;
}

public function 会員購入(AcceptanceTester $I)
public function 注文確認_会員購入(AcceptanceTester $I)
{
$I->wantTo('EF0901-UC01-T09_会員購入');

Expand Down Expand Up @@ -295,4 +295,88 @@ public function 会員購入(AcceptanceTester $I)
ShoppingPage::at($I)->確認する();
$I->see('試行回数の上限を超過しました。しばらくお待ちいただき、再度お試しください。', 'p.ec-reportDescription');
}

/**
* checkoutでのスロットリングのテスト
* confirmでの制限に引っかかるため、confirmLimiterの上限値を変更してから実施してください。
*
* @param AcceptanceTester $I
* @return void
*/
public function 注文完了_非会員購入(AcceptanceTester $I)
{
$I->wantTo('EF0901-UC01-T08_非会員購入');

$I->logoutAsMember();

for ($i = 0; $i < 25; $i++) {
$I->expect('非会員購入を行います:'.$i);
// カートへ進む
ProductDetailPage::go($I, 2)->カートに入れる(1)->カートへ進む();
// レジに進む
CartPage::go($I)->レジに進む();
// 非会員情報入力
$ShoppingPage = ShoppingLoginPage::at($I)->ゲスト購入();
$this->inputGuestInfo($ShoppingPage)->次へ();
// 注文確認画面へ
ShoppingPage::at($I)->確認する();
// 注文完了
ShoppingConfirmPage::at($I)->注文する();
$I->see('ご注文完了', 'div.ec-pageHeader h1');
}

$I->expect('試行回数上限を超過します');
// カートへ進む
ProductDetailPage::go($I, 2)->カートに入れる(1)->カートへ進む();
// レジに進む
CartPage::go($I)->レジに進む();
// 非会員情報入力
$ShoppingPage = ShoppingLoginPage::at($I)->ゲスト購入();
$this->inputGuestInfo($ShoppingPage)->次へ();
// 注文確認画面へ
ShoppingPage::at($I)->確認する();
// 注文完了
ShoppingConfirmPage::at($I)->注文する();
$I->see('購入処理で予期しないエラーが発生しました。恐れ入りますがお問い合わせページよりご連絡ください。', 'div.ec-cartRole__error');
}

/**
* checkoutでのスロットリングのテスト
* confirmでの制限に引っかかるため、confirmLimiterの上限値を変更してから実施してください。
*
* @param AcceptanceTester $I
* @return void
*/
public function 注文完了_会員購入(AcceptanceTester $I)
{
$I->wantTo('EF0901-UC01-T09_会員購入');

$createCustomer = Fixtures::get('createCustomer');
$customer = $createCustomer();
$I->loginAsMember($customer->getEmail(), 'password');

for ($i = 0; $i < 10; $i++) {
$I->expect('会員購入を行います:'.$i);
// カートへ進む
ProductDetailPage::go($I, 2)->カートに入れる(1)->カートへ進む();
// レジに進む
CartPage::go($I)->レジに進む();
// 注文確認画面へ
ShoppingPage::at($I)->確認する();
// 注文完了
ShoppingConfirmPage::at($I)->注文する();
$I->see('ご注文完了', 'div.ec-pageHeader h1');
}

$I->expect('試行回数上限を超過します');
// カートへ進む
ProductDetailPage::go($I, 2)->カートに入れる(1)->カートへ進む();
// レジに進む
CartPage::go($I)->レジに進む();
// 注文確認画面へ
ShoppingPage::at($I)->確認する();
// 注文完了
ShoppingConfirmPage::at($I)->注文する();
$I->see('購入処理で予期しないエラーが発生しました。恐れ入りますがお問い合わせページよりご連絡ください。', 'div.ec-cartRole__error');
}
}
27 changes: 26 additions & 1 deletion src/Eccube/Controller/ShoppingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ class ShoppingController extends AbstractShoppingController

protected RateLimiterFactory $shoppingConfirmCustomerLimiter;

protected RateLimiterFactory $shoppingCheckoutIpLimiter;

protected RateLimiterFactory $shoppingCheckoutCustomerLimiter;

public function __construct(
CartService $cartService,
MailService $mailService,
Expand All @@ -88,7 +92,9 @@ public function __construct(
ContainerInterface $serviceContainer,
TradeLawRepository $tradeLawRepository,
RateLimiterFactory $shoppingConfirmIpLimiter,
RateLimiterFactory $shoppingConfirmCustomerLimiter
RateLimiterFactory $shoppingConfirmCustomerLimiter,
RateLimiterFactory $shoppingCheckoutIpLimiter,
RateLimiterFactory $shoppingCheckoutCustomerLimiter
) {
$this->cartService = $cartService;
$this->mailService = $mailService;
Expand All @@ -98,6 +104,8 @@ public function __construct(
$this->tradeLawRepository = $tradeLawRepository;
$this->shoppingConfirmIpLimiter = $shoppingConfirmIpLimiter;
$this->shoppingConfirmCustomerLimiter = $shoppingConfirmCustomerLimiter;
$this->shoppingCheckoutIpLimiter = $shoppingCheckoutIpLimiter;
$this->shoppingCheckoutCustomerLimiter = $shoppingCheckoutCustomerLimiter;
}

/**
Expand Down Expand Up @@ -421,6 +429,23 @@ public function checkout(Request $request)
return $response;
}

log_info('[注文完了] IPベースのスロットリングを実行します.');
$ipLimiter = $this->shoppingCheckoutIpLimiter->create($request->getClientIp());
if (!$ipLimiter->consume()->isAccepted()) {
log_info('[注文完了] 試行回数制限を超過しました(IPベース)');
throw new TooManyRequestsHttpException();
}

$Customer = $this->getUser();
if ($Customer instanceof Customer) {
log_info('[注文完了] 会員ベースのスロットリングを実行します.');
$customerLimiter = $this->shoppingCheckoutCustomerLimiter->create($Customer->getId());
if (!$customerLimiter->consume()->isAccepted()) {
log_info('[注文完了] 試行回数制限を超過しました(会員ベース)');
throw new TooManyRequestsHttpException();
}
}

log_info('[注文処理] PaymentMethodを取得します.', [$Order->getPayment()->getMethodClass()]);
$paymentMethod = $this->createPaymentMethod($Order, $form);

Expand Down

0 comments on commit 5f56720

Please sign in to comment.