You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CodeIgniter3中PDF文件存储位置及登录用户访问权限方案咨询

CodeIgniter 3 PDF存储与权限控制最优方案

刚好之前在CodeIgniter 3里折腾过类似的需求,给你一套经过验证的靠谱方案,分存储位置和权限控制两部分讲清楚:

一、存储位置:放在Web根目录之外

绝对不要把PDF放在Web根目录(比如public_html或者项目里index.php所在的文件夹),不然用户只要知道文件名就能直接访问。最优选择是Web根目录的上级目录,举个典型的项目结构:

/var/www/
├─ my_ci_project/  # Web根目录,包含index.php
└─ ci_pdfs/        # 专门存PDF的目录,Web服务器不直接映射

这么做的核心好处:

  • 彻底避免HTTP直接访问,哪怕服务器配置出错也不会泄露文件
  • 完全脱离Web服务的直接管控,安全性拉满

然后在CodeIgniter里配置这个路径:打开application/config/config.php,添加全局常量方便后续调用:

define('PDF_STORAGE_PATH', '/var/www/ci_pdfs'); // 替换成你实际的路径

二、权限控制:通过控制器中转访问

核心思路是不让用户直接接触文件,所有PDF请求都经过CodeIgniter控制器验证权限,具体步骤如下:

1. 创建权限验证控制器

新建application/controllers/PdfController.php,负责处理所有PDF的访问请求:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class PdfController extends CI_Controller {

    public function __construct() {
        parent::__construct();
        // 确保session库已加载(如果没在autoload里配置的话)
        $this->load->library('session');
    }

    public function view($file_id) {
        // 第一步:检查用户是否登录
        if (!$this->session->userdata('logged_in')) {
            redirect('auth/login'); // 跳转到你的登录页面
            return;
        }

        // 第二步:从数据库获取PDF关联记录(建议把PDF信息存在数据库)
        $this->load->model('Pdf_model');
        $pdf_record = $this->Pdf_model->get_pdf_by_id($file_id);

        // 第三步:验证PDF是否属于当前用户(防止越权访问)
        if (!$pdf_record || $pdf_record['user_id'] != $this->session->userdata('user_id')) {
            show_404(); // 返回404,不让用户知道文件存在
            return;
        }

        $pdf_path = PDF_STORAGE_PATH . '/' . $pdf_record['filename'];

        // 第四步:安全校验,防止路径遍历攻击(比如../../etc/passwd)
        if (!file_exists($pdf_path) || realpath($pdf_path) !== realpath(PDF_STORAGE_PATH . '/' . basename($pdf_record['filename']))) {
            show_404();
            return;
        }

        // 第五步:输出PDF给用户(inline是在线预览,attachment是强制下载)
        header('Content-Type: application/pdf');
        header('Content-Disposition: inline; filename="' . $pdf_record['filename'] . '"');
        header('Content-Length: ' . filesize($pdf_path));

        readfile($pdf_path);
        exit;
    }
}

2. 配套数据库模型

新建application/models/Pdf_model.php,用来操作PDF的关联记录:

<?php
class Pdf_model extends CI_Model {
    public function get_pdf_by_id($file_id) {
        // 假设你有个`pdfs`表,字段包括id, user_id, filename, created_at
        return $this->db->get_where('pdfs', ['id' => $file_id])->row_array();
    }
}

3. 生成PDF时的存储逻辑

当你用TCPDF/dompdf生成PDF后,保存到指定目录并记录到数据库:

// 示例:用TCPDF生成PDF
$this->load->library('tcpdf');
$pdf = new TCPDF();
// ... 这里写你的PDF内容生成代码 ...

// 生成唯一文件名,避免重名和恶意覆盖
$unique_filename = 'user_' . $this->session->userdata('user_id') . '_' . time() . '_' . uniqid() . '.pdf';
// 保存到外部目录
$pdf->output(PDF_STORAGE_PATH . '/' . $unique_filename, 'F');

// 记录到数据库,方便后续关联用户和权限验证
$this->db->insert('pdfs', [
    'user_id' => $this->session->userdata('user_id'),
    'filename' => $unique_filename,
    'created_at' => date('Y-m-d H:i:s')
]);

三、额外安全细节

  • 设置存储目录权限:给ci_pdfs目录设置chmod 700,确保只有Web服务器用户(比如www-data)能读写,其他用户无法访问
  • 验证文件类型:可以用finfo_file检查文件实际是PDF,防止恶意文件混入
  • 限制请求频率:可以加个简单的限流逻辑,防止恶意请求刷接口

内容的提问来源于stack exchange,提问作者Tikky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:22:05