From 522d2f8128d066cc94b46e2aa2bca076c274c5c8 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 7 Dec 2023 15:22:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=BE=E5=BD=A2=E9=AA=8C=E8=AF=81=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/AuthController.php | 9 ++- app/Http/Controllers/CaptchaController.php | 71 +++++++++++++++++++ app/Services/CaptchaService.php | 82 ++++++++++++++++++++++ routes/api.php | 3 + 4 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/CaptchaController.php create mode 100644 app/Services/CaptchaService.php diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index d461d26..aa78ffd 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use App\Models\AdminPermission; use App\Models\AdminUser; +use App\Services\CaptchaService; use Illuminate\Contracts\Cache\Repository as Cache; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; @@ -15,13 +16,19 @@ class AuthController extends Controller ) { } - public function login(Request $request) + public function login(Request $request, CaptchaService $captchaService) { $request->validate([ 'username' => 'required', 'password' => 'required', + 'captcha_key' => 'required', + 'captcha_value' => 'required', ]); + if (! $captchaService->testPhrase($request->input('captcha_key'), $request->input('captcha_value'))) { + return $this->error('验证码错误'); + } + $username = $request->input('username'); $user = AdminUser::where(['username' => $username])->first(); diff --git a/app/Http/Controllers/CaptchaController.php b/app/Http/Controllers/CaptchaController.php new file mode 100644 index 0000000..ad19e01 --- /dev/null +++ b/app/Http/Controllers/CaptchaController.php @@ -0,0 +1,71 @@ +validate([ + 'key' => ['bail', 'filled', 'string', 'max:32'], + 'w' => ['bail', 'int'], + 'h' => ['bail', 'int'], + ]); + + $builder = $this->builder(); + $builder->build($request->input('w', 150), $request->input('h', 40)); + + $captchaService->put( + $key = $request->input('key', Str::random(16)), + $builder->getPhrase() + ); + + return response()->json([ + 'key' => $key, + 'img' => $builder->inline(), + ]); + } + + /** + * 查看图形验证码 + * + * @param string $key + * @param \Illuminate\Http\Request $request + * @param \App\Services\CaptchaService $captchaService + * @return \Illuminate\Http\Response + */ + public function show($key, Request $request, CaptchaService $captchaService) + { + $builder = $this->builder(); + $builder->build( + (int) $request->query('w', 150), + (int) $request->query('h', 40), + ); + + if (strlen($key) <= 32) { + $captchaService->put($key, $builder->getPhrase()); + } + + return response($builder->get()) + ->header('Content-Type', 'image/jpeg') + ->header('Cache-Control', 'no-cache'); + } + + /** + * 图形验证码生成器 + * + * @return \Gregwar\Captcha\CaptchaBuilder + */ + protected function builder(): CaptchaBuilder + { + return new CaptchaBuilder(Str::random(5)); + } +} diff --git a/app/Services/CaptchaService.php b/app/Services/CaptchaService.php new file mode 100644 index 0000000..fa58a02 --- /dev/null +++ b/app/Services/CaptchaService.php @@ -0,0 +1,82 @@ +cache->put($this->cacheKey($key), $phrase, $ttl); + } + + /** + * 校验验证码是否正确 + * + * @param string $key + * @param string $phrase + * @return bool + */ + public function testPhrase(string $key, string $phrase): bool + { + if ($phrase === '') { + return false; + } + + $value = (string) $this->cache->pull( + $this->cacheKey($key) + ); + + return strtolower($value) === strtolower($phrase); + } + + /** + * 校验验证码是否正确 + * + * @param string $key + * @param string $phrase + * @return void + * + * @throws \App\Exceptions\BizException + */ + public function validatePhrase(string $key, string $phrase): void + { + if (! $this->testPhrase($key, $phrase)) { + throw new BizException(__('Invalid captcha')); + } + } + + /** + * 生成验证码缓存的 key + * + * @param string $key + * @return string + */ + protected function cacheKey(string $key): string + { + return $this->cachePrefix.$key; + } +} diff --git a/routes/api.php b/routes/api.php index 262c2d4..24839b0 100644 --- a/routes/api.php +++ b/routes/api.php @@ -17,6 +17,9 @@ use Illuminate\Support\Facades\Route; Route::post('auth/login', [AuthController::class, 'login']); +Route::post('captchas', [CaptchaController::class, 'store']); +Route::get('captchas/{captcha}', [CaptchaController::class, 'show']); + Route::group([ 'middleware' => ['auth:sanctum'], ], function () {