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

如何限制未登录用户通过ViewerJS URL访问服务器文件?

解决未登录用户绕过ViewerJS直接访问上传文件的问题

看起来你踩了个常见的坑:ViewerJS是直接让浏览器请求了uploads目录下的静态文件,这个请求根本没经过你定义的ViewerJS/*路由。因为你的F3路由只拦截针对ViewerJS/路径的请求,但文件URL是../uploads/2138970950.pdf,浏览器会直接向这个路径发请求,完全绕开了你的路由校验。

下面给你几个可靠的解决方案,按推荐程度排序:

方案1:将uploads目录移出Web根,通过F3路由代理文件访问

这是最安全的做法,彻底断绝直接访问文件的可能:

  1. 调整文件目录结构:把uploads文件夹从gbdportal-new/(Web根目录)移到Web根外面,比如和gbdportal-new同级的位置,这样外部无法直接通过URL访问到它。
  2. 添加F3路由校验登录:定义一个专门的路由来处理文件请求,先验证用户登录状态,再返回文件内容:
$f3->route('GET /secure-files/@filename', function($f3) {
    // 这里替换成你的登录校验逻辑,比如检查session中的用户标识
    if (!isset($_SESSION['logged_in_user']) || $_SESSION['logged_in_user'] !== true) {
        $f3->error(403, "请先登录以访问该文件");
        return;
    }

    // 安全处理文件名,防止路径遍历攻击(关键!)
    $safeFilename = basename($f3->get('PARAMS.filename'));
    $filePath = '../uploads/' . $safeFilename; // 这里是你移出Web根后的uploads路径

    // 检查文件是否存在且是合法文件
    if (!file_exists($filePath) || !is_file($filePath)) {
        $f3->error(404, "文件不存在");
        return;
    }

    // 设置正确的HTTP头,让浏览器正确解析文件
    $mime = mime_content_type($filePath);
    header("Content-Type: $mime");
    header("Content-Length: " . filesize($filePath));
    
    // 输出文件内容
    readfile($filePath);
});
  1. 修改ViewerJS的访问路径:把原来的../uploads/2138970950.pdf改成/secure-files/2138970950.pdf,最终ViewerJS的URL变成:
    http://localhost/gbdportal-new/ViewerJS/#/secure-files/2138970950.pdf

这样所有文件请求都会经过F3的路由校验,未登录用户会直接收到403禁止访问的响应。

方案2:用服务器配置(Apache/Nginx)拦截uploads请求到F3

如果不想移动uploads目录,可以通过Web服务器的重写规则,把所有对uploads的请求转发到F3的入口文件,再由F3做登录校验:

如果你用Apache(.htaccess)

在gbdportal-new/目录下的.htaccess中添加:

RewriteEngine On
# 拦截uploads的请求,转发到index.php处理
RewriteRule ^uploads/(.*)$ index.php?file=uploads/$1 [L]

然后在F3的入口文件中处理file参数,逻辑和方案1类似:校验登录→检查文件合法性→返回内容。

如果你用Nginx

在站点配置中添加:

location /uploads/ {
    rewrite ^/uploads/(.*)$ /index.php?file=uploads/$1 last;
}

同样在F3中处理file参数即可。

方案3:修改ViewerJS的文件加载逻辑(不推荐)

ViewerJS本身是前端工具,默认直接访问文件URL。你可以修改它的源码,让它通过你的后端接口获取文件二进制内容,再进行渲染。但这个方案需要深入ViewerJS的代码,维护成本高,除非你有特殊需求,否则不建议用。

关键安全提醒

  • 无论用哪个方案,一定要处理文件名的安全性:用basename()或者F3的$f3->clean()方法过滤文件名,防止用户构造../../etc/passwd这样的路径进行遍历攻击。
  • 登录校验逻辑要严谨:确保session没有被伪造,比如用F3的内置session机制而非自己手写。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:41:21