
通过后端验证控制文件下载,而非依赖前端链接或 web 服务器静态拦截,可确保用户必须登录且拥有权限才能获取敏感资源。
通过后端验证控制文件下载,而非依赖前端链接或 web 服务器静态拦截,可确保用户必须登录且拥有权限才能获取敏感资源。
在 Web 开发中,将敏感文件(如 /book/mybook.pdf)直接暴露在 Web 根目录下会导致严重的安全风险:即使页面上使用了 <a href="/book/mybook.pdf" download></a> 触发下载,用户仍可通过浏览器地址栏直接输入 URL(如 https://www.mysite.com/book/mybook.pdf)绕过所有业务逻辑,实现未授权访问。
你尝试在 web.config 中通过 <requestfiltering></requestfiltering> 禁用 .pdf 扩展名的直接访问,虽然阻止了 URL 直连,但也同时阻断了合法下载——因为该配置是全局、无条件的静态拦截,不区分请求来源、用户身份或上下文。这不是正确的解决方案。
✅ 正确做法是:移除对静态文件的粗粒度拦截,将所有文件访问路由收口至 PHP 脚本,并由 PHP 完成身份验证与权限校验后,再安全输出文件内容。
✅ 推荐实现方案(基于 PHP + IIS / web.config)
1. 重写文件访问路径(避免暴露真实路径)
将 HTML 中的下载链接改为指向受控 PHP 脚本:
<a href="/download.php?file=mybook.pdf" download="mybook.pdf">下载电子书</a>
2. 创建 download.php 进行权限校验与安全输出
<?php // download.php —— 统一入口,强制认证 + 白名单校验 + 安全响应
session_start();
// ① 强制登录检查(示例:需存在有效用户会话)
if (!isset($_SESSION['user_id']) || $_SESSION['user_id'] <= 0) {
http_response_code(403);
die('Access denied: Please log in first.');
}
// ② 白名单机制:仅允许下载预定义的、合法的文件(防路径遍历)
$allowed_files = ['mybook.pdf', 'manual_v2.pdf', 'license.pdf']; // 生产环境建议从数据库或配置加载
$requested_file = basename($_GET['file'] ?? '');
if (!in_array($requested_file, $allowed_files)) {
http_response_code(404);
die('File not found.');
}
// ③ 构建绝对安全路径(禁止跨目录访问)
$base_dir = __DIR__ . '/book/';
$file_path = $base_dir . $requested_file;
if (!is_file($file_path) || !is_readable($file_path)) {
http_response_code(404);
die('File unavailable.');
}
// ④ 安全输出:设置正确 headers,防止浏览器缓存敏感内容
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . $requested_file . '"');
header('Content-Length: ' . filesize($file_path));
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Expires: 0');
readfile($file_path);
exit;3. (可选)配合 web.config 增强防护(IIS 环境)
若需进一步屏蔽对 /book/ 目录的直接访问,可在 web.config 中添加 URL 重写规则(而非 requestFiltering),将 /book/* 请求全部重定向或返回 403,但保留 download.php 的正常执行权限:
<configuration><system.webserver><rewrite><rules><rule name="Block direct book access" stopprocessing="true"><match url="^book/.*"></match><conditions logicalgrouping="MatchAll"><add input="{URL}" pattern="^/download\.php$" negate="true"></add></conditions><action type="CustomResponse" statuscode="403" statusreason="Forbidden"></action></rule></rules></rewrite></system.webserver></configuration>⚠️ 注意事项
- ❌ 不要依赖前端
download属性或隐藏链接来实现安全——它们完全可被绕过; - ✅ 所有敏感文件应存放于 Web 根目录 之外(如
../private/book/),从根本上杜绝 HTTP 直连可能(推荐); - ✅
download.php中务必使用basename()防止?file=../../etc/passwd类路径遍历攻击; - ✅ 生产环境建议结合角色权限系统(如检查用户是否购买了该书籍),而不仅是登录态;
- ✅ 对大文件下载,考虑使用
fpassthru()或流式读取,避免内存溢出。
通过此方案,你既保留了用户友好的点击下载体验,又彻底消除了未授权直连风险——安全与可用性兼得。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











