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

如何从非公开存储文件夹读取文件并在前端安全展示?解决readfile失效问题

从非公开存储文件夹安全展示文件的解决方案

核心思路是通过后端代理脚本做中间层:先验证用户授权,再读取非公开文件夹里的文件输出给前端,绝对不能让前端直接访问非公开路径。下面给两种可行的实现方法:

方法一:PHP代理脚本(通用方案)

适合大多数PHP环境,补全权限验证和安全校验后,readfile就能正常工作:

<?php
// 第一步:权限验证(按你的业务逻辑调整,比如检查用户登录状态)
session_start();
// 示例:仅登录且有权限的用户可访问
if (!isset($_SESSION['user_id']) || $_SESSION['user_role'] !== 'authorized') {
    http_response_code(403);
    exit('未授权访问');
}

// 第二步:严格校验文件名,防止路径遍历攻击
// 维护允许访问的文件白名单,绝对不能直接用用户输入拼接路径!
$allowed_files = ['something.jpg', 'report.pdf', 'data.xlsx'];
$target_file = $_GET['file'] ?? '';

if (!in_array($target_file, $allowed_files)) {
    http_response_code(404);
    exit('文件不存在');
}

// 第三步:拼接非公开文件夹的绝对路径(要放在网站根目录之外)
$private_folder = '/var/private_storage/';
$file_path = $private_folder . $target_file;

// 第四步:检查文件是否存在且可读
if (!file_exists($file_path) || !is_readable($file_path)) {
    http_response_code(404);
    exit('文件不存在或无法读取');
}

// 第五步:设置响应头,让浏览器识别文件类型
$mime_type = mime_content_type($file_path);
header("Content-Type: $mime_type");
header("Content-Length: " . filesize($file_path));

// 输出文件内容
readfile($file_path);
exit;
?>

关键注意事项:

  • 非公开文件夹必须放在网站根目录之外,比如/var/private_storage/,不能是/var/www/html/private/,避免用户直接通过URL访问。
  • 权限验证必须做:用session、JWT等方式验证用户身份,确保只有授权用户能获取文件。
  • 文件名必须用白名单过滤:禁止直接使用$_GET['file']拼接路径,防止攻击者用../../etc/passwd这类路径遍历攻击。
  • 确保PHP进程有读取该文件夹的权限:比如给/var/private_storage/设置www-data用户可读权限。

方法二:Nginx X-Accel-Redirect(高效方案,适合大文件)

如果服务器用Nginx,这个方法比PHP直接输出更高效——文件传输交给Nginx处理,PHP只负责权限校验:

1. PHP校验脚本(比如serve_private.php)

<?php
session_start();
// 先做权限验证
if (!isset($_SESSION['user_id']) || !$_SESSION['has_access']) {
    http_response_code(403);
    exit('未授权访问');
}

$allowed_files = ['something.jpg'];
$target_file = $_GET['file'] ?? '';

if (!in_array($target_file, $allowed_files)) {
    http_response_code(404);
    exit('文件不存在');
}

// 告诉Nginx内部重定向到私有文件路径
header("X-Accel-Redirect: /internal/private/" . $target_file);
// 可选:禁止缓存,或按需设置缓存策略
header("Cache-Control: no-cache");
exit;
?>

2. Nginx配置修改

在站点配置中添加以下内容:

location /internal/private/ {
    internal; # 仅允许内部请求,禁止用户直接访问
    root /var/private_storage/; # 指向你的非公开文件夹
}

前端调用方式

不管用哪种方法,前端都通过代理脚本访问文件:

<!-- 展示图片 -->
<img src="/serve_private_file.php?file=something.jpg" alt="私有图片">

<!-- 下载文件 -->
<a href="/serve_private_file.php?file=report.pdf" download>下载私有报告</a>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 20:15:39