PHP 怎么PHP 权限日志

wen PHP项目 3

本文目录导读:

PHP 怎么PHP 权限日志

  1. 基础权限日志系统
  2. 权限检查与日志记录中间件
  3. 使用示例
  4. 日志管理功能
  5. 性能优化建议
  6. 安全考虑

我来详细说明PHP权限日志的实现方法:

基础权限日志系统

数据库表结构

CREATE TABLE permission_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    username VARCHAR(50),
    action VARCHAR(50) NOT NULL,
    resource VARCHAR(100),
    resource_id INT,
    status TINYINT(1) DEFAULT 1, -- 1成功 0失败
    ip_address VARCHAR(45),
    user_agent TEXT,
    detail TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user_id (user_id),
    INDEX idx_action (action),
    INDEX idx_created_at (created_at)
);

PHP实现类

<?php
class PermissionLogger {
    private $db;
    private $logConfig;
    public function __construct($dbConnection) {
        $this->db = $dbConnection;
        $this->logConfig = [
            'enabled' => true,
            'log_level' => 'info', // error, warning, info, debug
            'retention_days' => 90,
            'log_methods' => ['database', 'file'] // 支持多种存储方式
        ];
    }
    /**
     * 记录权限日志
     */
    public function log($userId, $action, $resource, $resourceId = null, 
                       $status = true, $detail = null) {
        try {
            if (!$this->logConfig['enabled']) {
                return false;
            }
            // 获取用户信息
            $userInfo = $this->getUserInfo($userId);
            $logData = [
                'user_id' => $userId,
                'username' => $userInfo['username'] ?? 'Unknown',
                'action' => $action,
                'resource' => $resource,
                'resource_id' => $resourceId,
                'status' => $status ? 1 : 0,
                'ip_address' => $this->getClientIP(),
                'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
                'detail' => $detail ? json_encode($detail) : null,
                'created_at' => date('Y-m-d H:i:s')
            ];
            // 保存到数据库
            $this->saveToDatabase($logData);
            // 保存到文件
            if (in_array('file', $this->logConfig['log_methods'])) {
                $this->saveToFile($logData);
            }
            return true;
        } catch (Exception $e) {
            error_log("Permission log error: " . $e->getMessage());
            return false;
        }
    }
    /**
     * 保存到数据库
     */
    private function saveToDatabase($data) {
        $sql = "INSERT INTO permission_logs 
                (user_id, username, action, resource, resource_id, 
                 status, ip_address, user_agent, detail, created_at) 
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([
            $data['user_id'],
            $data['username'],
            $data['action'],
            $data['resource'],
            $data['resource_id'],
            $data['status'],
            $data['ip_address'],
            $data['user_agent'],
            $data['detail'],
            $data['created_at']
        ]);
    }
    /**
     * 保存到文件
     */
    private function saveToFile($data) {
        $logDir = __DIR__ . '/logs/permission/';
        if (!is_dir($logDir)) {
            mkdir($logDir, 0755, true);
        }
        $logFile = $logDir . date('Y-m-d') . '.log';
        $logLine = sprintf(
            "[%s] [%s] [User:%s] [Action:%s] [Resource:%s] [Status:%s] [IP:%s] %s\n",
            $data['created_at'],
            $data['status'] ? 'SUCCESS' : 'FAILURE',
            $data['username'],
            $data['action'],
            $data['resource'] . ($data['resource_id'] ? "({$data['resource_id']})" : ''),
            $data['status'] ? 'Allowed' : 'Denied',
            $data['ip_address'],
            $data['detail'] ?: ''
        );
        file_put_contents($logFile, $logLine, FILE_APPEND | LOCK_EX);
    }
    /**
     * 获取客户端IP
     */
    private function getClientIP() {
        $ipKeys = [
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_REAL_IP',
            'HTTP_CLIENT_IP',
            'REMOTE_ADDR'
        ];
        foreach ($ipKeys as $key) {
            if (isset($_SERVER[$key])) {
                $ip = $_SERVER[$key];
                if (filter_var($ip, FILTER_VALIDATE_IP)) {
                    return $ip;
                }
            }
        }
        return '0.0.0.0';
    }
    /**
     * 获取用户信息
     */
    private function getUserInfo($userId) {
        // 这里应该从用户表查询
        $sql = "SELECT id, username, role FROM users WHERE id = ?";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$userId]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
}

权限检查与日志记录中间件

<?php
class PermissionMiddleware {
    private $logger;
    private $permissions;
    public function __construct($db) {
        $this->logger = new PermissionLogger($db);
        $this->permissions = [
            'admin' => ['create', 'read', 'update', 'delete'],
            'editor' => ['create', 'read', 'update'],
            'viewer' => ['read']
        ];
    }
    /**
     * 检查权限并记录日志
     */
    public function checkPermission($userId, $requiredAction, $resource) {
        try {
            // 获取用户角色
            $userRole = $this->getUserRole($userId);
            // 检查权限
            $hasPermission = $this->hasPermission($userRole, $requiredAction);
            // 记录权限检查日志
            $this->logger->log(
                $userId,
                $hasPermission ? 'PERMISSION_CHECK' : 'PERMISSION_DENIED',
                $resource,
                null,
                $hasPermission,
                [
                    'role' => $userRole,
                    'required_action' => $requiredAction,
                    'has_permission' => $hasPermission
                ]
            );
            if (!$hasPermission) {
                throw new \Exception("权限不足:需要 {$requiredAction} 权限");
            }
            return true;
        } catch (Exception $e) {
            // 记录异常
            $this->logger->log(
                $userId,
                'PERMISSION_ERROR',
                $resource,
                null,
                false,
                ['error' => $e->getMessage()]
            );
            throw $e;
        }
    }
    private function getUserRole($userId) {
        // 从数据库查询用户角色
        $sql = "SELECT role FROM users WHERE id = ?";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$userId]);
        return $stmt->fetchColumn();
    }
    private function hasPermission($role, $action) {
        return isset($this->permissions[$role]) && 
               in_array($action, $this->permissions[$role]);
    }
}

使用示例

<?php
// 初始化
$db = new PDO('mysql:host=localhost;dbname=test', 'root', 'password');
$permissionLog = new PermissionLogger($db);
$permissionMiddleware = new PermissionMiddleware($db);
// 记录简单的权限操作
$permissionLog->log(
    1,                      // 用户ID
    'LOGIN',               // 操作类型
    'system',              // 资源
    null,                  // 资源ID
    true,                  // 是否成功
    ['login_method' => 'password']  // 详细信息
);
// 记录文件访问权限
$permissionLog->log(
    2,
    'FILE_ACCESS',
    'document',
    123,
    true,
    ['file_path' => '/uploads/document.pdf', 'action' => 'download']
);
// 使用中间件检查权限
try {
    $permissionMiddleware->checkPermission(
        $userId,
        'delete',
        'article'
    );
    // 执行删除操作
} catch (Exception $e) {
    echo $e->getMessage();
}

日志管理功能

<?php
class PermissionLogManager {
    private $db;
    public function __construct($db) {
        $this->db = $db;
    }
    /**
     * 查询权限日志
     */
    public function queryLogs($filters = [], $page = 1, $perPage = 20) {
        $where = [];
        $params = [];
        if (!empty($filters['user_id'])) {
            $where[] = "user_id = ?";
            $params[] = $filters['user_id'];
        }
        if (!empty($filters['action'])) {
            $where[] = "action = ?";
            $params[] = $filters['action'];
        }
        if (!empty($filters['status'])) {
            $where[] = "status = ?";
            $params[] = $filters['status'];
        }
        if (!empty($filters['date_from'])) {
            $where[] = "created_at >= ?";
            $params[] = $filters['date_from'];
        }
        if (!empty($filters['date_to'])) {
            $where[] = "created_at <= ?";
            $params[] = $filters['date_to'];
        }
        $whereClause = $where ? 'WHERE ' . implode(' AND ', $where) : '';
        // 计算总数
        $countSql = "SELECT COUNT(*) FROM permission_logs {$whereClause}";
        $countStmt = $this->db->prepare($countSql);
        $countStmt->execute($params);
        $total = $countStmt->fetchColumn();
        // 获取分页数据
        $offset = ($page - 1) * $perPage;
        $sql = "SELECT * FROM permission_logs {$whereClause} 
                ORDER BY created_at DESC LIMIT ? OFFSET ?";
        $params[] = $perPage;
        $params[] = $offset;
        $stmt = $this->db->prepare($sql);
        $stmt->execute($params);
        $logs = $stmt->fetchAll(PDO::FETCH_ASSOC);
        return [
            'total' => $total,
            'page' => $page,
            'per_page' => $perPage,
            'data' => $logs
        ];
    }
    /**
     * 清理过期日志
     */
    public function cleanOldLogs($days = 90) {
        $sql = "DELETE FROM permission_logs WHERE created_at < DATE_SUB(NOW(), INTERVAL ? DAY)";
        $stmt = $this->db->prepare($sql);
        return $stmt->execute([$days]);
    }
    /**
     * 导出日志
     */
    public function exportLogs($filters = []) {
        $logs = $this->queryLogs($filters, 1, 1000000);
        header('Content-Type: text/csv');
        header('Content-Disposition: attachment; filename="permission_logs.csv"');
        $output = fopen('php://output', 'w');
        fputcsv($output, ['ID', 'User', 'Action', 'Resource', 'Status', 'IP', 'Time']);
        foreach ($logs['data'] as $log) {
            fputcsv($output, [
                $log['id'],
                $log['username'],
                $log['action'],
                $log['resource'] . ' (' . $log['resource_id'] . ')',
                $log['status'] ? 'Success' : 'Failed',
                $log['ip_address'],
                $log['created_at']
            ]);
        }
        fclose($output);
        exit;
    }
}

性能优化建议

  1. 使用消息队列:对于高并发场景,将日志写入内存队列
  2. 定期归档:将旧日志归档到单独的表或文件
  3. 索引优化:在常用查询字段上建立索引
  4. 缓存热点数据:使用Redis缓存最近的日志

安全考虑

  • 对敏感信息进行脱敏处理
  • 日志文件权限设置为600
  • 限制日志查询的访问权限
  • 对日志API进行速率限制

这个系统可以帮助你全面记录和管理权限相关的操作,便于审计和问题排查。

抱歉,评论功能暂时关闭!