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

如何配置.htaccess实现私有目录图片的安全访问(PHP+Apache环境)

解决PHP+Apache环境下私有目录图片的安全访问问题

问题背景

使用PHP+Apache环境,已配置路由使根目录(public目录)下的图片可正常显示,但无法加载private目录中的图片。需求是将图片存储在私有目录仅对所有者可见,且公开路径必须以"/"开头,不能使用"../",需确保本地与线上服务器均能正常运行。

项目结构

app/
-------/public     <======Root
---------------/css
---------------/img
---------------/js
---------------/index.php
---------------/.htaccess
-------/private
---------------/imgs    
---------------/pages
---------------/dashboard.php
-------/lib
-----------/route.php

当前.htaccess配置

AddType Content-Type: application / x-www-form-urlencoded

Options -MultiViews
RewriteEngine On 

RewriteCond %{REQUEST_FILENAME} !-f 

RewriteRule ^(.*)$ index.php? [QSA,L]

当前尝试的代码

HTML代码

<span> <img src="img/test2.jpg" width="30px"> </span>
<span> <img src="../private/imgs/test1.jpg" width="30px"> </span>

PHP尝试代码

<?php
    $directorio = "../private/imgs/";

    function printImagesDir($dir){
        $files = glob($dir.'*.{jpg,JPG,jpeg,JPEG,png,PNG}', GLOB_BRACE);
        foreach($files as $filename){
            $imgsrc = basename($filename);
            echo "<img src='{$dir}/{$imgsrc}' />";
        }        
    }

    printImagesDir($directorio);
?>

解决方案

核心思路是通过PHP中间层代理访问私有图片:直接通过URL访问private目录会被Apache拦截(不在根目录范围内),且不能使用相对路径,因此需要创建PHP接口处理图片请求,同时加入权限验证确保只有所有者能访问。

步骤1:创建图片代理接口

在public目录下新建serve-private-img.php文件,负责读取私有目录图片并输出:

<?php
// 1. 权限验证:根据业务逻辑添加校验,比如登录状态、用户权限
session_start();
if (!isset($_SESSION['user_id']) || $_SESSION['user_role'] !== 'owner') {
    http_response_code(403);
    exit('无权访问');
}

// 2. 过滤文件名,防止目录遍历攻击
$imgName = basename($_GET['img']);
$privateImgPath = __DIR__ . '/../private/imgs/' . $imgName;

// 3. 校验文件合法性
$allowedExts = ['jpg', 'jpeg', 'png', 'gif'];
$fileExt = strtolower(pathinfo($privateImgPath, PATHINFO_EXTENSION));

if (!file_exists($privateImgPath) || !in_array($fileExt, $allowedExts)) {
    http_response_code(404);
    exit('图片不存在');
}

// 4. 设置响应头并输出图片
$mimeTypes = [
    'jpg' => 'image/jpeg',
    'jpeg' => 'image/jpeg',
    'png' => 'image/png',
    'gif' => 'image/gif'
];
header("Content-Type: {$mimeTypes[$fileExt]}");
readfile($privateImgPath);
exit;
?>

步骤2:修改图片访问路径

将原有相对路径改为调用代理接口的绝对路径:

修改后的HTML代码

<span> <img src="img/test2.jpg" width="30px"> </span>
<!-- 调用代理接口访问私有图片 -->
<span> <img src="/serve-private-img.php?img=test1.jpg" width="30px"> </span>

修改后的PHP遍历代码

<?php
function printPrivateImages(){
    $privateImgDir = __DIR__ . '/../private/imgs/';
    $files = glob($privateImgDir.'*.{jpg,JPG,jpeg,JPEG,png,PNG}', GLOB_BRACE);
    foreach($files as $filename){
        $imgsrc = basename($filename);
        echo "<img src='/serve-private-img.php?img={$imgsrc}' width='30px' />";
    }        
}

printPrivateImages();
?>

步骤3:优化URL美观度(可选)

在.htaccess中添加规则,隐藏PHP后缀,让URL更规范:

# 私有图片路由美化
RewriteRule ^private-img/([a-zA-Z0-9_\-\.]+\.(jpg|jpeg|png|gif))$ serve-private-img.php?img=$1 [QSA,L]

之后可使用/private-img/test1.jpg的形式访问私有图片。

关键注意事项

  • 权限校验:必须在代理接口中加入严格的权限验证,确保只有合法用户能访问私有图片。
  • 路径安全:使用basename()过滤文件名,避免目录遍历攻击。
  • 兼容性:用__DIR__获取绝对路径,适配本地与服务器的目录结构差异。
  • MIME类型:正确设置响应头,保证浏览器能正常识别图片。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 12:43:19