feat: 添加 Laravel Sanctum 支持,增强管理员 API 鉴权,更新相关中间件与路由配置
This commit is contained in:
25
app/Http/Controllers/Api/V1/Admin/Auth/CaptchaController.php
Normal file
25
app/Http/Controllers/Api/V1/Admin/Auth/CaptchaController.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\Auth;
|
||||
|
||||
use App\Services\AdminCaptchaService;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* GET /api/v1/admin/auth/captcha
|
||||
*
|
||||
* 返回一次性验证码 Key 与 SVG(Base64 便于前台直接赋值给 img.src)。
|
||||
*/
|
||||
final class CaptchaController
|
||||
{
|
||||
public function __invoke(AdminCaptchaService $captcha): JsonResponse
|
||||
{
|
||||
$payload = $captcha->create();
|
||||
|
||||
return ApiResponse::success([
|
||||
'captcha_key' => $payload['captcha_key'],
|
||||
'image_base64' => $payload['image_base64'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
88
app/Http/Controllers/Api/V1/Admin/Auth/LoginController.php
Normal file
88
app/Http/Controllers/Api/V1/Admin/Auth/LoginController.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\Auth;
|
||||
|
||||
use App\Lottery\ErrorCode;
|
||||
use App\Models\AdminUser;
|
||||
use App\Services\AdminCaptchaService;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* POST /api/v1/admin/auth/login
|
||||
*
|
||||
* Body: account(登录账号,与 username 对应,ASCII 仅存小写比对)、password、captcha_key、captcha_code。
|
||||
*/
|
||||
final class LoginController
|
||||
{
|
||||
public function __invoke(Request $request, AdminCaptchaService $captcha): JsonResponse
|
||||
{
|
||||
$locale = $request->lotteryLocale();
|
||||
|
||||
/** @var array{account:string,password:string,captcha_key:string,captcha_code:string} $data */
|
||||
$data = validator($request->all(), [
|
||||
'account' => ['required', 'string', 'min:2', 'max:64', 'regex:/^[a-zA-Z0-9._-]+$/u'],
|
||||
'password' => ['required', 'string', 'max:256'],
|
||||
'captcha_key' => ['required', 'string', 'uuid'],
|
||||
'captcha_code' => ['required', 'string', 'max:32'],
|
||||
], [], [
|
||||
'account' => 'account',
|
||||
'password' => 'password',
|
||||
'captcha_key' => 'captcha_key',
|
||||
'captcha_code' => 'captcha_code',
|
||||
])->validate();
|
||||
|
||||
if (! $captcha->verify($data['captcha_key'], $data['captcha_code'])) {
|
||||
return ApiResponse::error(
|
||||
trans('admin.invalid_captcha', [], $locale),
|
||||
ErrorCode::AdminCaptchaInvalid->value,
|
||||
null,
|
||||
422,
|
||||
);
|
||||
}
|
||||
|
||||
$normalizedAccount = Str::lower(trim($data['account']));
|
||||
|
||||
/** @var AdminUser|null $admin */
|
||||
$admin = AdminUser::query()->where('username', $normalizedAccount)->first();
|
||||
|
||||
$passwordOk = $admin !== null && Hash::check($data['password'], $admin->password);
|
||||
|
||||
if (! $passwordOk) {
|
||||
/** 统一措辞,弱化枚举用户 */
|
||||
return ApiResponse::error(
|
||||
trans('admin.invalid_credentials', [], $locale),
|
||||
ErrorCode::AdminCredentialsInvalid->value,
|
||||
null,
|
||||
401,
|
||||
);
|
||||
}
|
||||
|
||||
if ((int) $admin->status !== 0) {
|
||||
return ApiResponse::error(
|
||||
trans('admin.account_disabled', [], $locale),
|
||||
ErrorCode::AdminAccountDisabled->value,
|
||||
null,
|
||||
403,
|
||||
);
|
||||
}
|
||||
|
||||
$plainToken = $admin->createToken('admin-api')->plainTextToken;
|
||||
|
||||
$admin->forceFill(['last_login_at' => now()])->save();
|
||||
|
||||
return ApiResponse::success([
|
||||
'token' => $plainToken,
|
||||
'token_type' => 'Bearer',
|
||||
'admin' => [
|
||||
'id' => $admin->id,
|
||||
'username' => $admin->username,
|
||||
'nickname' => $admin->name,
|
||||
'email' => $admin->email,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user