Implement ALTCHA captcha service with challenge generation and solution verification
- Added AltchaService class for managing ALTCHA captcha challenges and solutions. - Created CaptchaController to handle API requests for generating challenges. - Introduced CaptchaGuard for validating captcha solutions on public endpoints. - Developed unit tests for AltchaService to ensure challenge creation and solution verification functionality. - Implemented integration tests for the Captcha API endpoint and captcha bypass behavior when disabled. - Added documentation for the Captcha API in the corresponding markdown file.
This commit is contained in:
@@ -812,3 +812,50 @@ clinic-pro-symfony/
|
||||
> CSS فرانتاند از کلاسهای template اختصاصی استفاده میکند (نه Tailwind).
|
||||
> بعد از هر تغییر backend: `cache:clear`
|
||||
> بعد از هر تغییر entity: `migrations:diff` سپس `migrations:migrate`
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ ALTCHA — کپچای خودمیزبان (ضدِ اسپم/بات)
|
||||
|
||||
کپچای Proof-of-Work مبتنی بر [ALTCHA](https://altcha.org) — بدون تصویر، بدون تایپ، بدون سرویس خارجی (مناسب کاربران داخل ایران). فقط روی endpointهای **عمومی و بدون احراز هویت** اعمال میشود.
|
||||
|
||||
### نصب (انجامشده)
|
||||
- بکاند: `composer require altcha-org/altcha` (پکیج رسمی PHP، از V1 API استفاده میشود).
|
||||
- فرانتاند: `yarn add altcha` (web-component محلی، بدون CDN؛ Encore آن را bundle میکند).
|
||||
|
||||
### تنظیمات (`.env` / برای prod در `.env.local`)
|
||||
| متغیر | پیشفرض | توضیح |
|
||||
|---|---|---|
|
||||
| `ALTCHA_ENABLED` | `false` | در prod روی `true`؛ در dev/test غیرفعال بماند |
|
||||
| `ALTCHA_HMAC_KEY` | `change-me-in-env-local` | کلید امضای سرور — **حتماً در prod عوض شود** و مخفی بماند |
|
||||
| `ALTCHA_MAX_NUMBER` | `100000` | سقف اعداد PoW = **سختی**؛ بالاتر = سنگینتر برای مرورگر |
|
||||
| `ALTCHA_EXPIRE_SECONDS` | `300` | عمر هر challenge (ثانیه) |
|
||||
|
||||
### جریان
|
||||
1. کلاینت `GET /api/v1/altcha/challenge` را میگیرد (challenge امضاشده).
|
||||
2. `<altcha-widget>` در پسزمینه PoW را حل میکند.
|
||||
3. مقدار حلشده (base64) با کلید `altcha` در بدنهی درخواستِ endpoint عمومی ارسال میشود.
|
||||
4. سرور با `CaptchaGuard::assertValid($request)` اعتبارسنجی میکند (امضا + انقضا + یکبارمصرف بودن).
|
||||
|
||||
### endpointهای محافظتشده
|
||||
`send-code`، `register`، `otp-login`، `reset-password`، `pre-registration`.
|
||||
> `rate`/`comment` پشت JWT هستند و کپچا نمیگیرند (بیفایده است).
|
||||
|
||||
### افزودن کپچا به endpoint عمومی جدید
|
||||
`CaptchaGuard` را inject کن و اولین خط handler:
|
||||
```php
|
||||
$this->captcha->assertValid($request); // پرتاب ERR_CAPTCHA_001 (422) در صورت شکست
|
||||
```
|
||||
سپس مسیر را در فرانت به بدنهی درخواست `altcha` وصل کن.
|
||||
|
||||
### تغییر سختی
|
||||
`ALTCHA_MAX_NUMBER` را بالا/پایین ببر (مثلاً `1000000` برای سختتر).
|
||||
|
||||
### غیرفعالسازی
|
||||
`ALTCHA_ENABLED=false` → guard کاملاً no-op میشود (dev/test همیشه اینطور است).
|
||||
|
||||
### Troubleshooting
|
||||
- **همیشه ERR_CAPTCHA_001:** کلید `ALTCHA_HMAC_KEY` بین challenge و verify باید یکسان باشد؛ اگر بعد از صدور challenge کلید عوض شود، امضا نامعتبر میشود.
|
||||
- **challenge منقضی:** ساعت سرور را چک کن؛ `ALTCHA_EXPIRE_SECONDS` خیلی کوتاه نباشد.
|
||||
- **replay:** هر challenge یکبار مصرف است؛ برای هر submit یک challenge تازه بگیر.
|
||||
- **خطای Redis:** pool اختصاصی `altcha.pool` روی `REDIS_URL` است؛ در دسترس بودن Redis لازم است.
|
||||
|
||||
Reference in New Issue
Block a user