From d75a9e1ae1dbf9b0352afb47baf0fe06d807a707 Mon Sep 17 00:00:00 2001 From: "HESU\\HESU" <1696136552@qq.com> Date: Fri, 6 Jun 2025 10:38:31 +0800 Subject: [PATCH] =?UTF-8?q?=E7=99=BB=E5=BD=95=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/console/controller/AdminsController.php | 94 ++++++++++++++++++++ app/console/model/AdminsModel.php | 56 ++++++++++++ app/console/service/AdminsService.php | 98 +++++++++++++++++++++ app/console/validate/AdminsValidator.php | 29 ++++++ app/middleware/ConsoleAuthMiddleware.php | 69 +++++++++++++++ app/mzl/common/utils/JwtUtil.php | 59 +++++++++++++ config/jwt.php | 6 ++ config/middleware.php | 3 +- config/route.php | 2 + 9 files changed, 415 insertions(+), 1 deletion(-) create mode 100644 app/console/controller/AdminsController.php create mode 100644 app/console/model/AdminsModel.php create mode 100644 app/console/service/AdminsService.php create mode 100644 app/console/validate/AdminsValidator.php create mode 100644 app/middleware/ConsoleAuthMiddleware.php create mode 100644 app/mzl/common/utils/JwtUtil.php create mode 100644 config/jwt.php diff --git a/app/console/controller/AdminsController.php b/app/console/controller/AdminsController.php new file mode 100644 index 0000000..6045ccd --- /dev/null +++ b/app/console/controller/AdminsController.php @@ -0,0 +1,94 @@ +errorResponse($th->getMessage()); + } + } + + /** + * 登录 + */ + public function login(Request $request, string $scene = 'default'): Response + { + try { + $user =$this->getService()->login($request->all()); + return $this->successResponse($user); + } catch (\Throwable $th) { + return $this->errorResponse($th->getMessage().$th->getFile().$th->getLine()); + } + } +} \ No newline at end of file diff --git a/app/console/model/AdminsModel.php b/app/console/model/AdminsModel.php new file mode 100644 index 0000000..f873a9e --- /dev/null +++ b/app/console/model/AdminsModel.php @@ -0,0 +1,56 @@ + function ($params) { + // $keyword = $params['keyword'] ?? ''; + // return [ + // 'filters' => [ + // ['field' => '***', 'operator' => '=', 'value' => '***'] + // ], + // 'fields' => ['id'], + // 'relations' => [], + // 'custom' => function(Builder $q) use ($keyword) { + // // 示例 + // if ($keyword) { + // $q->where(function($q2) use($keyword) { + // $q2->whereHas('***', function($q3) use($keyword) { + // $q3->where('***', 'like', "%{$keyword}%"); + // })->orWhereHas('***', function($q4) use($keyword) { + // $q4->where('***', 'like', "%{$keyword}%"); + // }); + // }); + // } + // }, + // 'sorts' => [ + // ['field' => 'created_at', 'direction' => 'desc'] + // ], + // 'pagination' => [ + // 'page' => $params['page'] ?? 1, + // 'per_page' => $params['per_page'] ?? 10, + // ] + // ]; + // } + ]; + } + + public function login(array $params) + { + $sourceLocale = locale(); + + try { + if (empty($params['username'])) { + throw new BusinessException('用户名不能为空'); + } + if (empty($params['password'])) { + throw new BusinessException('密码不能为空'); + } + $admin = AdminsModel::where(['username'=>$params['username']])->first(); + if (!$admin) { + throw new BusinessException('用户不存在'); + } + $userId = $admin['id']; + + $adminPassword = $admin['password']; + + // $hashedPassword = password_hash($params['password'], PASSWORD_DEFAULT); //注册时的加密方法 + if (!password_verify($params['password'], $adminPassword)) { + throw new BusinessException('密码错误'); + } + + //密码验证成功后加密生成 Token + $token = JwtUtil::generateToken($userId); + $result = $admin; + unset($result['password']); + $result['token'] = $token; + + return $admin; + } catch (\Throwable $th) { + throw $th; + } + } +} \ No newline at end of file diff --git a/app/console/validate/AdminsValidator.php b/app/console/validate/AdminsValidator.php new file mode 100644 index 0000000..3569050 --- /dev/null +++ b/app/console/validate/AdminsValidator.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/middleware/ConsoleAuthMiddleware.php b/app/middleware/ConsoleAuthMiddleware.php new file mode 100644 index 0000000..615a380 --- /dev/null +++ b/app/middleware/ConsoleAuthMiddleware.php @@ -0,0 +1,69 @@ +path(), '/console/') !== 0) { + return $handler($request); + } + // 通过反射获取控制器哪些方法不需要登录 + $controller = new ReflectionClass($request->controller); + $noNeedLogin = $controller->getDefaultProperties()['noNeedJwt'] ?? []; + + $isLogin = !in_array($request->action, $noNeedLogin); + + // 从 Header 获取 Token + $token = $request->header('Authorization'); + + //需要登录并且未提供token + $body = [ + 'status' => 'error', + 'code' => 401, + 'message' => 'Please log in.', + 'data' => [], + ]; + if ($isLogin && (!$token || !str_starts_with($token, 'Bearer '))) { + return response(json_encode($body, JSON_UNESCAPED_UNICODE), 401, ['Content-Type' => 'application/json']); + }elseif(!$isLogin){ + return $handler($request); + } + + + $token = substr($token, 7); + try { + // 验证 Token 并获取用户ID + $decoded = JwtUtil::verifyToken($token); + + if (!isset($decoded->sub)) { + return response(json_encode($body, JSON_UNESCAPED_UNICODE), 401, ['Content-Type' => 'application/json']); + } + + $userId = $decoded->sub; + $user = AdminsModel::find($userId); + if(!$user){ + return response(json_encode($body, JSON_UNESCAPED_UNICODE), 401, ['Content-Type' => 'application/json']); + } + + // 将用户ID存入请求对象,供后续使用 + $request->user = $user; + return $handler($request); + } catch (BusinessException $e) { + return json(['code' => 401, 'msg' => $e->getMessage()]); + } + } +} \ No newline at end of file diff --git a/app/mzl/common/utils/JwtUtil.php b/app/mzl/common/utils/JwtUtil.php new file mode 100644 index 0000000..109b49a --- /dev/null +++ b/app/mzl/common/utils/JwtUtil.php @@ -0,0 +1,59 @@ + 'webman', // 签发者 + 'aud' => 'client', // 接收方 + 'iat' => time(), // 签发时间 + 'exp' => time() + $config['expire'], // 过期时间 + 'sub' => $userId // 用户标识 + ]; + return JWT::encode($payload, $config['secret'], $config['algorithm']); + } + + /** + * 验证并解析 Token + * @param string $token + * @return object + * @throws BusinessException + */ + public static function verifyToken(string $token) + { + $config = config('jwt'); + $body = [ + 'status' => 'error', + 'code' => 403, + 'message' => 'Please log in.', + 'data' => [], + ]; + try { + return JWT::decode($token, new Key($config['secret'], $config['algorithm'])); + } catch (ExpiredException $e) { + $body['message'] = 'Token Expired'; + return response(json_encode($body, JSON_UNESCAPED_UNICODE), 401, ['Content-Type' => 'application/json']); + } catch (SignatureInvalidException $e) { + $body['message'] = 'Signature Invalid'; + return response(json_encode($body, JSON_UNESCAPED_UNICODE), 401, ['Content-Type' => 'application/json']); + } catch (\Exception $e) { + $body['message'] = 'Invalid Token'; + return response(json_encode($body, JSON_UNESCAPED_UNICODE), 401, ['Content-Type' => 'application/json']); + } + } +} \ No newline at end of file diff --git a/config/jwt.php b/config/jwt.php new file mode 100644 index 0000000..6caa560 --- /dev/null +++ b/config/jwt.php @@ -0,0 +1,6 @@ + getenv('JWT_SECRET_KEY'), // 替换为高强度的密钥 + 'algorithm' => getenv('JWT_ALGORITHM'), // 加密算法 + 'expire' => getenv('JWT_EXPIRATION'), // 过期时间 +]; \ No newline at end of file diff --git a/config/middleware.php b/config/middleware.php index eadd331..8dee216 100644 --- a/config/middleware.php +++ b/config/middleware.php @@ -23,6 +23,7 @@ return [ app\middleware\Lang::class ], 'console' => [ - app\middleware\Lang::class + app\middleware\Lang::class, + app\middleware\ConsoleAuthMiddleware::class, ] ]; \ No newline at end of file diff --git a/config/route.php b/config/route.php index d9244dd..d16b36c 100644 --- a/config/route.php +++ b/config/route.php @@ -120,6 +120,8 @@ Route::group('/applet', function() { // ====== ====== ====== 后台管理 ====== ====== ====== Route::group('/console', function() { + // 协议管理 + Route::any('/user/login', [\app\console\controller\AdminsController::class, 'login']); // 协议管理 Route::any('/agt/list', [\app\console\controller\AgreementController::class, 'index']); Route::any('/agt/add', [\app\console\controller\AgreementController::class, 'add']);