guanguans/dcat-login-captcha
guanguans/dcat-login-captcha is a Laravel package that adds a configurable captcha to the Dcat Admin login page, helping protect admin authentication from bots and brute-force attempts. It installs quickly and integrates cleanly with Dcat Admin, with options for customizing the login captcha experie...
guanguans/dcat-login-captcha adds a CAPTCHA challenge to the Dcat Admin login screen. It is a thin integration layer around gregwar/captcha, so most of your day-to-day work is configuration, not code.
Install into an existing Dcat Admin app:
composer require guanguans/dcat-login-captcha
Publish the config and inspect it before touching anything else:
php artisan vendor:publish --provider="Guanguans\DcatLoginCaptcha\DcatLoginCaptchaServiceProvider"
The published config/dcat-login-captcha.php is the primary control surface (enable/disable, length, width/height, charset, fonts, route/middleware). Confirm the exact keys against the published file rather than relying on docs — the package evolves faster than its README.
Clear cached config/routes/views, then log out and load /admin/auth/login. The CAPTCHA image and input field should appear above/below the credentials.
First use case: turn it on in production only. Set the enabled flag from an env var so local and CI environments skip the challenge:
'enabled' => env('DCAT_LOGIN_CAPTCHA_ENABLED', true),
Then verify one full round trip: load login → read image → submit correct code → submit wrong code → confirm the image regenerates and the error is surfaced on the form.
Environment-scoped enablement. Keep CAPTCHA on for production/staging, off for local and testing. Drive it from env rather than editing config per machine; this is the single highest-value setup decision because it prevents developer and CI friction.
Treat the config as the API. Rendering, validation, and route registration are wired through the service provider. Tune difficulty via length/charset and readability via dimensions and font settings rather than subclassing internals. If you need a custom look, prefer swapping the font file in config over overriding the generator.
Reuse the generator outside the login form. Anywhere you need a CAPTCHA (custom admin registration, password reset, a public contact form), resolve the same gregwar/captcha builder from the container and register a matching route + validation rule. Doing this keeps one session key convention and one expiry policy across the app instead of two competing implementations.
Validation placement. Keep CAPTCHA validation in the same Form Request / controller path as the credential check so a failed CAPTCHA never reaches the auth guard. This avoids polluting login-throttle counters with bot traffic.
Refresh UX. On failed login, force a new image (append a cache-busting query param or increment a nonce) — reusing a stale image is the most common "it works but feels broken" complaint. If your login form is PJAX/AJAX-driven (Dcat's default), make sure the image src is re-rendered as part of the response, not just the DOM swapped around it.
Testing pattern. In feature tests, disable the CAPTCHA via config in phpunit.xml and assert the login path normally; keep a small dedicated test suite that re-enables it and drives the validation rule with a mocked/known session value. Don't attempt OCR in tests.
Observability. Log CAPTCHA validation failures at info with the route and IP — a spike is a useful bot signal, and a sudden drop to zero usually means the route broke or the session stopped persisting.
gregwar/captcha needs the GD extension with FreeType support. Verify php -m | grep -i gd and that a TTF font path resolves on every node; missing fonts manifest as blank images, not exceptions.gregwar/captcha to ^2.1; no package API changed. Upgrade risk is low but not zero: confirm your PHP version and GD/FreeType build still satisfy the 2.x constraint, and re-render one image after upgrading. If you were pinned to gregwar/captcha 1.x yourself, resolve that conflict before bumping.array or a stateless API guard, the CAPTCHA code never persists between image request and submit. Use a real session driver; for multi-node deployments ensure sticky sessions or a shared store.route:cache can break closure-based routes. If the image endpoint is registered as a closure, php artisan route:cache will fail or the route will vanish from the cache. Test your deploy pipeline with route caching enabled.Cache-Control: no-store (and bypass any CDN rule matching /admin/*). A cached CAPTCHA image is an unsolvable login form — and one of the hardest bugs to diagnose because it only appears behind the CDN.php artisan config:clear (or config:cache) — otherwise env-driven toggles silently do nothing.throttle middleware on the login route, remember CAPTCHA failures still consume attempts unless you validate CAPTCHA before hitting the limiter. Decide deliberately which behaviour you want.composer update guanguans/dcat-login-captcha plus config/route cache clear is sufficient. Re-run your login smoke test afterwards, since a silent font/render regression is the realistic failure mode.How can I help you explore Laravel packages today?