3, self::ROLE_ADMIN => 2, self::ROLE_OPERATOR => 1, ]; // 角色中文名称 const ROLE_NAMES = [ self::ROLE_SUPER_ADMIN => '超级管理员', self::ROLE_ADMIN => '管理员', self::ROLE_OPERATOR => '操作员', ]; // ========== 管理类目常量定义 ========== const CATEGORY_MES = 'mes'; // MES 制造执行 const CATEGORY_INVENTORY = 'inventory'; // 进销存 const CATEGORY_FINANCE = 'finance'; // 财务管理 const CATEGORY_GENERAL = 'general'; // 综合管理 const CATEGORY_ALL = 'all'; // 所有类目(仅超级管理员) // 类目中文名称 const CATEGORY_NAMES = [ self::CATEGORY_MES => 'MES 制造执行', self::CATEGORY_INVENTORY => '进销存管理', self::CATEGORY_FINANCE => '财务管理', self::CATEGORY_GENERAL => '综合管理', ]; // 类目图标 const CATEGORY_ICONS = [ self::CATEGORY_MES => 'fa-industry', self::CATEGORY_INVENTORY => 'fa-cubes', self::CATEGORY_FINANCE => 'fa-cny', self::CATEGORY_GENERAL => 'fa-th-large', ]; // 类目对应的首页控制器/action const CATEGORY_HOME = [ self::CATEGORY_MES => 'Admin/index', self::CATEGORY_INVENTORY => 'Inventory/index', self::CATEGORY_FINANCE => 'Finance/index', self::CATEGORY_GENERAL => 'General/index', ]; /** * 获取角色层级数值 */ public static function getRoleLevel($role) { return self::ROLE_LEVEL[$role] ?? 0; } /** * 检查当前用户角色是否不低于指定角色 */ public static function roleAtLeast($role, $minRole) { return self::getRoleLevel($role) >= self::getRoleLevel($minRole); } /** * 获取用户可访问的类目列表 * 超级管理员返回所有类目,管理员/操作员返回其分配的单一类目 */ public static function getUserCategories($user) { if (($user['role'] ?? '') === self::ROLE_SUPER_ADMIN) { return [self::CATEGORY_MES, self::CATEGORY_INVENTORY, self::CATEGORY_FINANCE, self::CATEGORY_GENERAL]; } $cat = $user['category'] ?? self::CATEGORY_MES; return [$cat]; } /** * 检查用户是否有指定类目的访问权限 */ public static function canAccessCategory($user, $category) { if (($user['role'] ?? '') === self::ROLE_SUPER_ADMIN) { return true; } return ($user['category'] ?? '') === $category; } /** * 获取类目选择列表(用于创建管理员时选择分配类目) */ public static function getCategoryOptions() { return self::CATEGORY_NAMES; } public function __construct($controller, $action) { $this->_controller = $controller; $this->_action = $action; $this->_view = new View($controller, $action); } // 分配变量 public function assign($name, $value) { $this->_view->assign($name, $value); } // 渲染视图 public function render() { $this->_view->render(); } // 检查登录状态 protected function checkLogin() { if (!isset($_SESSION['user_id']) || !isset($_SESSION['emp_no'])) { header('Location: ' . BASE_URL . '/Login/index'); exit; } return true; } /** * CSRF Token 生成 */ protected function csrfToken() { if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; } /** * CSRF Token 验证 * @param bool $graceful 为 true 时返回 false 而非直接 exit(供登录页优雅降级) * @return bool */ protected function csrfVerify($graceful = false) { $token = $_POST['csrf_token'] ?? ''; $sessionToken = $_SESSION['csrf_token'] ?? ''; if (empty($sessionToken) || !hash_equals($sessionToken, $token)) { // 诊断日志:记录失败原因和客户端信息,便于排查 Session 丢失问题 $reason = empty($sessionToken) ? 'session_token_empty' : 'token_mismatch'; $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $ua = isset($_SERVER['HTTP_USER_AGENT']) ? substr($_SERVER['HTTP_USER_AGENT'], 0, 200) : 'unknown'; $sessionId = session_id() ? hash('sha256', session_id()) : 'none'; error_log("[CSRF_FAIL] reason={$reason} ip={$ip} session_hash={$sessionId} ua={$ua}"); if ($graceful) { // 登录页优雅模式:清除旧 token,让页面重新生成 unset($_SESSION['csrf_token']); return false; } // 其他页面保持原有行为:直接拒绝(CSRF 攻击风险) // AJAX 请求返回 JSON,避免前端因无法解析响应而只能报“网络错误” if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') { header('Content-Type: application/json; charset=utf-8'); echo json_encode(['success' => false, 'error' => '安全验证失败,请刷新页面后重试']); exit; } exit('安全验证失败,请刷新页面后重试'); } return true; } /** * 以 JSON 方式输出并终止;会先清空已缓冲的输出(警告/空白等), * 避免响应被污染导致前端无法解析 JSON(表现为“网络错误”)。 */ protected function jsonExit($data, $httpCode = 200) { if (ob_get_level() > 0) { ob_end_clean(); } if ($httpCode !== 200) { http_response_code($httpCode); } header('Content-Type: application/json; charset=utf-8'); echo json_encode($data, JSON_UNESCAPED_UNICODE); exit; } /** * 验证请求方法(用于删除等危险操作) */ protected function requireMethod($method) { if ($_SERVER['REQUEST_METHOD'] !== strtoupper($method)) { exit('不允许的请求方法'); } return true; } /** * 安全转义输出(XSS防护) */ protected function h($str) { return htmlspecialchars((string)$str, ENT_QUOTES, 'UTF-8'); } // 检测是否为 AJAX 请求 protected function isAjax() { return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'; } // 获取当前登录用户 protected function getCurrentUser() { return array( 'id' => isset($_SESSION['user_id']) ? (int)$_SESSION['user_id'] : 0, 'emp_no' => isset($_SESSION['emp_no']) ? $_SESSION['emp_no'] : '', 'emp_name' => isset($_SESSION['emp_name']) ? $_SESSION['emp_name'] : '', 'role' => isset($_SESSION['role']) ? $_SESSION['role'] : self::ROLE_OPERATOR, 'category' => isset($_SESSION['category']) ? $_SESSION['category'] : self::CATEGORY_MES ); } /** * 检查是否为后台管理角色(超级管理员或管理员) */ protected function requireAdminRole() { $user = $this->getCurrentUser(); $role = $user['role']; if ($role !== self::ROLE_SUPER_ADMIN && $role !== self::ROLE_ADMIN) { header('Location: ' . BASE_URL . '/Front/index'); exit; } return $user; } /** * 获取指定角色的可管理角色列表 * 超级管理员可管理所有人;管理员只能管理操作员;操作员无管理权限 */ public static function getManageableRoles($role) { if ($role === self::ROLE_SUPER_ADMIN) { return [self::ROLE_SUPER_ADMIN, self::ROLE_ADMIN, self::ROLE_OPERATOR]; } if ($role === self::ROLE_ADMIN) { return [self::ROLE_ADMIN, self::ROLE_OPERATOR]; } return []; } // 退出登录 public function loginout() { session_destroy(); header('Location: /'); exit; } }