adminModel = new Admin(); $this->config = require __DIR__ . '/../config/app.php'; } /** * 用户登录 */ public function login($username, $password) { if (empty($username) || empty($password)) { return ['code' => 400, 'msg' => '用户名和密码不能为空']; } $admin = $this->adminModel->findByUsername($username); if (!$admin) { return ['code' => 400, 'msg' => '用户名或密码错误']; } if ($admin['status'] != 1) { return ['code' => 403, 'msg' => '账号已被禁用,请联系管理员']; } if (!password_verify($password, $admin['password'])) { return ['code' => 400, 'msg' => '用户名或密码错误']; } // 更新登录信息 $ip = $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1'; $this->adminModel->updateLoginInfo($admin['id'], $ip); // 生成Token $token = $this->generateToken($admin); return [ 'code' => 200, 'msg' => '登录成功', 'data' => [ 'token' => $token, 'userinfo' => [ 'id' => $admin['id'], 'username' => $admin['username'], 'nickname' => $admin['nickname'] ?: $admin['username'], 'avatar' => $admin['avatar'] ?: '', 'category' => $admin['category'] ?? 'mes', 'role' => ($admin['category'] === 'all') ? 'super_admin' : 'admin', ], ], ]; } /** * 生成JWT Token */ private function generateToken($admin) { $header = base64_encode(json_encode([ 'alg' => 'HS256', 'typ' => 'JWT', ])); $payload = base64_encode(json_encode([ 'id' => $admin['id'], 'username' => $admin['username'], 'iat' => time(), 'exp' => time() + $this->config['token_expire'], ])); $signature = base64_encode(hash_hmac( 'sha256', "{$header}.{$payload}", $this->config['token_secret'], true )); return "{$header}.{$payload}.{$signature}"; } /** * 验证Token */ public function verifyToken($token) { if (empty($token)) { return false; } $parts = explode('.', $token); if (count($parts) !== 3) { return false; } [$header, $payload, $signature] = $parts; // 验证签名 $expectedSig = base64_encode(hash_hmac( 'sha256', "{$header}.{$payload}", $this->config['token_secret'], true )); if (!hash_equals($expectedSig, $signature)) { return false; } // 解析payload $data = json_decode(base64_decode($payload), true); if (!$data) { return false; } // 检查过期 if (isset($data['exp']) && $data['exp'] < time()) { return false; } return $data; } /** * 获取当前登录用户 */ public function getCurrentUser() { $token = $this->getBearerToken(); if (!$token) { return null; } $payload = $this->verifyToken($token); if (!$payload) { return null; } return $this->adminModel->find($payload['id']); } /** * 从请求头获取Token * 优先级: Authorization > X-Auth-Token (Nginx兼容) */ public function getBearerToken() { // 1. 标准 Authorization header $headers = $this->getAuthorizationHeader(); if ($headers && preg_match('/Bearer\s+(.+)$/i', $headers, $matches)) { return $matches[1]; } // 2. 自定义 header X-Auth-Token (Nginx 默认不丢弃自定义 header) // 前端发送: X-Auth-Token: Bearer $xAuthToken = $_SERVER['HTTP_X_AUTH_TOKEN'] ?? null; if ($xAuthToken) { if (preg_match('/^Bearer\s+(.+)$/i', $xAuthToken, $m)) { return $m[1]; } // 也支持直接传 token 值 return $xAuthToken; } // 3. URL 参数 token(用于 window.open / 下载等场景) $urlToken = $_GET['token'] ?? null; if ($urlToken) { return $urlToken; } return null; } /** * 获取Authorization头 * 兼容 Apache / Nginx / IIS / PHP-FPM 等多种环境 */ private function getAuthorizationHeader() { // 1. Apache / Nginx (with pass) 标准 if (isset($_SERVER['HTTP_AUTHORIZATION'])) { return $_SERVER['HTTP_AUTHORIZATION']; } // 2. Apache rewrite 后 if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { return $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; } // 3. Nginx + PHP-FPM: Authorization 可能被放在其他变量中 if (isset($_SERVER['AUTHORIZATION'])) { return $_SERVER['AUTHORIZATION']; } // 4. apache_request_headers (Apache/FastCGI) if (function_exists('apache_request_headers')) { $headers = apache_request_headers(); if (isset($headers['Authorization'])) { return $headers['Authorization']; } // 有些环境下 header 名是小写的 if (isset($headers['authorization'])) { return $headers['authorization']; } } // 5. Nginx + PHP-FPM 终极兜底: 从原始 HTTP 头中提取 // 有些 Nginx 配置下,Authorization 可能根本不在 $_SERVER 中 // 尝试从 getallheaders() 获取 (PHP-FPM built-in) if (function_exists('getallheaders')) { $allHeaders = getallheaders(); if (isset($allHeaders['Authorization'])) { return $allHeaders['Authorization']; } if (isset($allHeaders['authorization'])) { return $allHeaders['authorization']; } } return null; } /** * 生成密码哈希 */ public function hashPassword($password) { return password_hash($password, PASSWORD_BCRYPT); } }