Skip to content

Commit 9ed141c

Browse files
authored
Merge pull request #30 from ray-di/claude/review-csrf-protection-yjrZA
2 parents 300ebc9 + 35e2425 commit 9ed141c

4 files changed

Lines changed: 70 additions & 26 deletions

File tree

.claude/skills/migrate-to-1.0/SKILL.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ becomes
8282
Also add `use Ray\WebFormModule\Annotation\CsrfProtection;`.
8383

8484
If `antiCsrf=false` (or omitted), drop the option without adding
85-
`#[CsrfProtection]` — methods without the attribute perform no CSRF check.
85+
`#[CsrfProtection]`. The method itself then performs no attribute-driven
86+
CSRF check; the form may still enforce CSRF if it uses `SetAntiCsrfTrait`
87+
(see "Out of scope" below).
8688

8789
### 1c. `@InputValidation` and `@VndError`
8890

@@ -194,7 +196,8 @@ Report to the user:
194196
- Migrating other libraries' annotations (only `Ray\WebFormModule\Annotation\*`).
195197
- Renaming `SetAntiCsrfTrait` — the trait and `setAntiCsrf()` method are
196198
unchanged in 1.0.
197-
- Changes to forms that use `AntiCsrf` without `#[CsrfProtection]`
198-
flag these to the user: in 1.0 they will silently stop enforcing CSRF.
199-
The user must decide whether to add `#[CsrfProtection]` to the validated
200-
controller method or accept the new behaviour.
199+
- Deciding whether `#[CsrfProtection]` added by Step 1b is redundant. Forms
200+
that already use `SetAntiCsrfTrait` enforce CSRF via `AbstractForm::apply()`
201+
regardless of the attribute, so the attribute Step 1b inserts is harmless
202+
but unnecessary. Flag these to the user so they can drop the attribute if
203+
they prefer a single declaration site.

.markdownlint.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"MD046": {
3+
"style": "fenced"
4+
}
5+
}

README.JA.md

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,20 +127,26 @@ class MyController
127127

128128
### CSRF Protections
129129

130-
CSRF対策は **opt-in** です。`SetAntiCsrfTrait` を使うフォームには `AntiCsrfInterface` が注入されますが、
131-
トークンの検証は `#[CsrfProtection]` 属性が付いたメソッドでのみ行われます。
132-
`#[CsrfProtection]` が無いメソッドでは、フォーム側に AntiCsrf がセットされていても CSRF チェックは実行されません。
130+
CSRF対策は **opt-in** で、独立した 2 つの経路のいずれかで有効化できます。
131+
132+
- **フォーム単位**: フォームに `use SetAntiCsrfTrait;` を追加します。
133+
Ray.Di がトレイトの `#[Inject]` setter 経由で `AntiCsrfInterface` を注入し、
134+
`postConstruct()` でトークンフィールドが追加され、`apply()` の呼び出しごとに
135+
トークンが検証されます。
136+
- **アクション単位**: バリデーション対象のコントローラメソッドに
137+
`#[CsrfProtection]` を付与します。`AuraInputInterceptor``apply()` 実行前に
138+
`AntiCsrfInterface` をフォームへ注入します。
139+
140+
どちらの経路でも、トークン不一致時には `AbstractForm::apply()`
141+
`CsrfViolationException` を throw します。どちらも使わない場合は CSRF 検証は
142+
行われません。両方を併用しても害はありませんが冗長なので、用途に合わせて
143+
どちらか一方を選んでください。
144+
145+
アクション単位 — コントローラのメソッドで宣言:
133146

134147
```php
135-
use Ray\WebFormModule\AbstractAuraForm;
136148
use Ray\WebFormModule\Annotation\CsrfProtection;
137149
use Ray\WebFormModule\Annotation\FormValidation;
138-
use Ray\WebFormModule\SetAntiCsrfTrait;
139-
140-
class MyForm extends AbstractAuraForm
141-
{
142-
use SetAntiCsrfTrait;
143-
}
144150

145151
class MyController
146152
{
@@ -152,6 +158,18 @@ class MyController
152158
}
153159
```
154160

161+
フォーム単位 — フォーム自身で宣言:
162+
163+
```php
164+
use Ray\WebFormModule\AbstractForm;
165+
use Ray\WebFormModule\SetAntiCsrfTrait;
166+
167+
class MyForm extends AbstractForm
168+
{
169+
use SetAntiCsrfTrait;
170+
}
171+
```
172+
155173
セキュリティレベルを高めるためにはユーザーの認証を含んだカスタムCsrfクラスを作成してフォームクラスにセットします。
156174
詳しくはAura.Inputの[Applying CSRF Protections](https://github.com/auraphp/Aura.Input#applying-csrf-protections)をご覧ください。
157175

README.md

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -142,21 +142,26 @@ or render input element basis.
142142
```
143143
### CSRF Protections
144144

145-
CSRF protection is **opt-in**. A form that uses `SetAntiCsrfTrait` is wired
146-
with an `AntiCsrfInterface`, but the token is only verified when the
147-
validated method is annotated with `#[CsrfProtection]`. Methods without
148-
`#[CsrfProtection]` perform no CSRF check even if the form supports it.
145+
CSRF protection is **opt-in** and can be enabled through either of two
146+
independent paths:
147+
148+
- **Per-form**: add `use SetAntiCsrfTrait;` to the form. `AntiCsrfInterface`
149+
is injected by Ray.Di through the trait's `#[Inject]` setter, the token
150+
field is added in `postConstruct()`, and every `apply()` call verifies
151+
the token.
152+
- **Per-action**: annotate the validated controller method with
153+
`#[CsrfProtection]`. `AuraInputInterceptor` then injects
154+
`AntiCsrfInterface` into the form before `apply()` runs.
155+
156+
Either path causes `AbstractForm::apply()` to throw `CsrfViolationException`
157+
on token mismatch. Without either path, no CSRF check is performed. Combining
158+
both paths is harmless but redundant — pick whichever fits your use case.
159+
160+
Per-action — declare CSRF on the controller method:
149161

150162
```php
151-
use Ray\WebFormModule\AbstractAuraForm;
152163
use Ray\WebFormModule\Annotation\CsrfProtection;
153164
use Ray\WebFormModule\Annotation\FormValidation;
154-
use Ray\WebFormModule\SetAntiCsrfTrait;
155-
156-
class MyForm extends AbstractAuraForm
157-
{
158-
use SetAntiCsrfTrait;
159-
}
160165

161166
class MyController
162167
{
@@ -167,6 +172,19 @@ class MyController
167172
}
168173
}
169174
```
175+
176+
Per-form — declare CSRF on the form itself:
177+
178+
```php
179+
use Ray\WebFormModule\AbstractForm;
180+
use Ray\WebFormModule\SetAntiCsrfTrait;
181+
182+
class MyForm extends AbstractForm
183+
{
184+
use SetAntiCsrfTrait;
185+
}
186+
```
187+
170188
You can provide your custom `AntiCsrf` class. See more detail at [Aura.Input](https://github.com/auraphp/Aura.Input#applying-csrf-protections)
171189

172190
## Migration from 0.x

0 commit comments

Comments
 (0)