图形验证码

dev
Jing Li 2023-12-07 15:22:50 +08:00
parent f0dc08c21c
commit 522d2f8128
4 changed files with 164 additions and 1 deletions

View File

@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use App\Models\AdminPermission; use App\Models\AdminPermission;
use App\Models\AdminUser; use App\Models\AdminUser;
use App\Services\CaptchaService;
use Illuminate\Contracts\Cache\Repository as Cache; use Illuminate\Contracts\Cache\Repository as Cache;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash; 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([ $request->validate([
'username' => 'required', 'username' => 'required',
'password' => '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'); $username = $request->input('username');
$user = AdminUser::where(['username' => $username])->first(); $user = AdminUser::where(['username' => $username])->first();

View File

@ -0,0 +1,71 @@
<?php
namespace App\Http\Controllers;
use App\Services\CaptchaService;
use Gregwar\Captcha\CaptchaBuilder;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class CaptchaController extends Controller
{
/**
* 创建图形验证码
*/
public function store(Request $request, CaptchaService $captchaService)
{
$request->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));
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace App\Services;
use App\Exceptions\BizException;
use Illuminate\Contracts\Cache\Repository as Cache;
class CaptchaService
{
/**
* @var string
*/
protected $cachePrefix = 'captchas_';
/**
* @param \Illuminate\Contracts\Cache\Repository $cache
*/
public function __construct(
protected Cache $cache,
) {
}
/**
* 将验证码存入缓存中
*
* @param string $key
* @param string $phrase
* @param integer $ttl
* @return void
*/
public function put(string $key, string $phrase, int $ttl = 300): void
{
$this->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;
}
}

View File

@ -17,6 +17,9 @@ use Illuminate\Support\Facades\Route;
Route::post('auth/login', [AuthController::class, 'login']); Route::post('auth/login', [AuthController::class, 'login']);
Route::post('captchas', [CaptchaController::class, 'store']);
Route::get('captchas/{captcha}', [CaptchaController::class, 'show']);
Route::group([ Route::group([
'middleware' => ['auth:sanctum'], 'middleware' => ['auth:sanctum'],
], function () { ], function () {