Skip to content

Commit ca731d6

Browse files
nobuhikoclaude
andcommitted
fix: レート制限メッセージを6回目の試行時に表示するよう修正
5回失敗後、6回目の試行時点でレート制限メッセージを表示するよう変更。 これまでは6回失敗後の7回目の試行で初めてメッセージが表示されていたため、 ユーザーが「7回目の入力が間違っていたからロックされた」と誤解する可能性があった。 - email_count >= 6 → >= 5 に変更 - ip_count >= 11 → >= 10 に変更 - PHPUnit/E2Eテストの境界値を調整 Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent eff3eb8 commit ca731d6

3 files changed

Lines changed: 30 additions & 30 deletions

File tree

data/class/helper/SC_Helper_LoginRateLimit.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ class SC_Helper_LoginRateLimit
4040
* ログイン試行失敗が制限を超えていないか確認します。
4141
*
4242
* レート制限ルール:
43-
* - 同一メールアドレス: 1時間に5回まで失敗を許可(6回目でブロック
44-
* - 同一IPアドレス: 1時間に10回まで失敗を許可(11回目でブロック
43+
* - 同一メールアドレス: 1時間に5回まで失敗を許可(6回目の試行でブロック&メッセージ表示
44+
* - 同一IPアドレス: 1時間に10回まで失敗を許可(11回目の試行でブロック&メッセージ表示
4545
*
4646
* セキュリティ考慮事項:
4747
* - アカウント列挙攻撃対策: 存在しないメールアドレスも同様にレート制限
@@ -71,7 +71,7 @@ public static function checkRateLimit($login_id, $ip_address)
7171
[$login_id]
7272
);
7373

74-
if ($email_count >= 6) {
74+
if ($email_count >= 5) {
7575
return [
7676
'allowed' => false,
7777
'reason' => 'email',
@@ -87,7 +87,7 @@ public static function checkRateLimit($login_id, $ip_address)
8787
[$ip_address]
8888
);
8989

90-
if ($ip_count >= 11) {
90+
if ($ip_count >= 10) {
9191
return [
9292
'allowed' => false,
9393
'reason' => 'ip',

e2e-tests/test/front_guest/login_error.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,23 +161,23 @@ test.describe.serial('ログインエラー表示とレート制限のテスト
161161
await page.goto('/mypage/login.php');
162162
});
163163

164-
await test.step('6回連続でログインに失敗します', async () => {
165-
for (let i = 0; i < 6; i++) {
164+
await test.step('5回連続でログインに失敗します', async () => {
165+
for (let i = 0; i < 5; i++) {
166166
await page.locator('#login_mypage input[name="login_email"]').fill(rateLimitEmail);
167167
await page.locator('#login_mypage input[name="login_pass"]').fill('wrongpassword');
168168
await page.locator('#login_mypage input[type="image"][name="log"]').click();
169169

170170
// AJAX処理完了を待つためエラーメッセージが表示されるまで待機
171171
await page.locator('#undercolumn_login #login_error_area').waitFor({ state: 'visible', timeout: 10000 });
172172

173-
// 6回目まではメールアドレスベースのエラーまたはIPベースのレート制限エラー
173+
// 5回目まではメールアドレスベースのエラーまたはIPベースのレート制限エラー
174174
const errorText = await page.locator('#undercolumn_login #login_error_area').textContent();
175175
// いずれかのエラーメッセージが表示されていればOK
176176
expect(errorText).toMatch(/|/);
177177
}
178178
});
179179

180-
await test.step('7回目の試行でレート制限エラーが表示されます', async () => {
180+
await test.step('6回目の試行でレート制限エラーが表示されます', async () => {
181181
await page.locator('#login_mypage input[name="login_email"]').fill(rateLimitEmail);
182182
await page.locator('#login_mypage input[name="login_pass"]').fill('wrongpassword');
183183

tests/class/helper/SC_Helper_LoginRateLimit/SC_Helper_LoginRateLimitTest.php

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,58 +55,58 @@ public function testCheckRateLimitWithinEmailLimitReturnsAllowed()
5555
$email = '[email protected]';
5656
$ip = '192.168.1.1';
5757

58-
// 4回の失敗を記録
59-
for ($i = 0; $i < 4; $i++) {
58+
// 3回の失敗を記録(制限よりも十分に少ない)
59+
for ($i = 0; $i < 3; $i++) {
6060
SC_Helper_LoginRateLimit_Ex::recordLoginAttempt($email, $ip, 'TestAgent', 0);
6161
}
6262

6363
$result = SC_Helper_LoginRateLimit_Ex::checkRateLimit($email, $ip);
6464

6565
$this->assertTrue($result['allowed']);
66-
$this->assertEquals(4, $result['email_count']);
66+
$this->assertEquals(3, $result['email_count']);
6767
}
6868

6969
/**
7070
* Test checkRateLimit at email limit boundary
7171
*
72-
* メールアドレスのレート制限境界値(5回)の場合、allowedを返す
72+
* メールアドレスのレート制限境界値(4回)の場合、allowedを返す(5回目の試行まで許可)
7373
*/
7474
public function testCheckRateLimitAtEmailLimitBoundaryReturnsAllowed()
7575
{
7676
$email = '[email protected]';
7777
$ip = '192.168.1.1';
7878

79-
// 5回の失敗を記録
80-
for ($i = 0; $i < 5; $i++) {
79+
// 4回の失敗を記録(5回目の試行まで許可、6回目でブロック)
80+
for ($i = 0; $i < 4; $i++) {
8181
SC_Helper_LoginRateLimit_Ex::recordLoginAttempt($email, $ip, 'TestAgent', 0);
8282
}
8383

8484
$result = SC_Helper_LoginRateLimit_Ex::checkRateLimit($email, $ip);
8585

8686
$this->assertTrue($result['allowed']);
87-
$this->assertEquals(5, $result['email_count']);
87+
$this->assertEquals(4, $result['email_count']);
8888
}
8989

9090
/**
9191
* Test checkRateLimit exceeds email limit
9292
*
93-
* メールアドレスのレート制限超過(6回以上)の場合、blockedを返す
93+
* メールアドレスのレート制限超過(5回以上)の場合、blockedを返す(6回目の試行でブロック)
9494
*/
9595
public function testCheckRateLimitExceedsEmailLimitReturnsBlocked()
9696
{
9797
$email = '[email protected]';
9898
$ip = '192.168.1.1';
9999

100-
// 6回の失敗を記録
101-
for ($i = 0; $i < 6; $i++) {
100+
// 5回の失敗を記録(6回目の試行でブロック)
101+
for ($i = 0; $i < 5; $i++) {
102102
SC_Helper_LoginRateLimit_Ex::recordLoginAttempt($email, $ip, 'TestAgent', 0);
103103
}
104104

105105
$result = SC_Helper_LoginRateLimit_Ex::checkRateLimit($email, $ip);
106106

107107
$this->assertFalse($result['allowed']);
108108
$this->assertEquals('email', $result['reason']);
109-
$this->assertEquals(6, $result['email_count']);
109+
$this->assertEquals(5, $result['email_count']);
110110
}
111111

112112
/**
@@ -118,56 +118,56 @@ public function testCheckRateLimitWithinIPLimitReturnsAllowed()
118118
{
119119
$ip = '192.168.1.1';
120120

121-
// 9回の失敗を異なるメールアドレスで記録
122-
for ($i = 0; $i < 9; $i++) {
121+
// 8回の失敗を異なるメールアドレスで記録(制限よりも十分に少ない)
122+
for ($i = 0; $i < 8; $i++) {
123123
SC_Helper_LoginRateLimit_Ex::recordLoginAttempt("test{$i}@example.com", $ip, 'TestAgent', 0);
124124
}
125125

126126
$result = SC_Helper_LoginRateLimit_Ex::checkRateLimit('[email protected]', $ip);
127127

128128
$this->assertTrue($result['allowed']);
129-
$this->assertEquals(9, $result['ip_count']);
129+
$this->assertEquals(8, $result['ip_count']);
130130
}
131131

132132
/**
133133
* Test checkRateLimit at IP limit boundary
134134
*
135-
* IPアドレスのレート制限境界値(10回)の場合、allowedを返す
135+
* IPアドレスのレート制限境界値(9回)の場合、allowedを返す
136136
*/
137137
public function testCheckRateLimitAtIPLimitBoundaryReturnsAllowed()
138138
{
139139
$ip = '192.168.1.1';
140140

141-
// 10回の失敗を異なるメールアドレスで記録
142-
for ($i = 0; $i < 10; $i++) {
141+
// 9回の失敗を異なるメールアドレスで記録(10回目の試行まで許可)
142+
for ($i = 0; $i < 9; $i++) {
143143
SC_Helper_LoginRateLimit_Ex::recordLoginAttempt("test{$i}@example.com", $ip, 'TestAgent', 0);
144144
}
145145

146146
$result = SC_Helper_LoginRateLimit_Ex::checkRateLimit('[email protected]', $ip);
147147

148148
$this->assertTrue($result['allowed']);
149-
$this->assertEquals(10, $result['ip_count']);
149+
$this->assertEquals(9, $result['ip_count']);
150150
}
151151

152152
/**
153153
* Test checkRateLimit exceeds IP limit
154154
*
155-
* IPアドレスのレート制限超過(11回以上)の場合、blockedを返す
155+
* IPアドレスのレート制限超過(10回以上)の場合、blockedを返す(11回目の試行でブロック)
156156
*/
157157
public function testCheckRateLimitExceedsIPLimitReturnsBlocked()
158158
{
159159
$ip = '192.168.1.1';
160160

161-
// 11回の失敗を異なるメールアドレスで記録
162-
for ($i = 0; $i < 11; $i++) {
161+
// 10回の失敗を異なるメールアドレスで記録(11回目の試行でブロック)
162+
for ($i = 0; $i < 10; $i++) {
163163
SC_Helper_LoginRateLimit_Ex::recordLoginAttempt("test{$i}@example.com", $ip, 'TestAgent', 0);
164164
}
165165

166166
$result = SC_Helper_LoginRateLimit_Ex::checkRateLimit('[email protected]', $ip);
167167

168168
$this->assertFalse($result['allowed']);
169169
$this->assertEquals('ip', $result['reason']);
170-
$this->assertEquals(11, $result['ip_count']);
170+
$this->assertEquals(10, $result['ip_count']);
171171
}
172172

173173
/**

0 commit comments

Comments
 (0)