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

如何通过Nginx结合CodeIgniter4为特定用户提供静态文件

解决Nginx结合CodeIgniter4提供用户专属静态文件的权限控制方案

以下是几个实用方案,既能让Nginx直接加速静态文件传输,又能依托CI4的登录体系完成权限校验:

方案一:FastCGI授权(推荐,无需额外Nginx模块)

利用Nginx的auth_request指令,让Nginx先请求CI4的授权接口验证用户权限,通过后再直接返回文件。

1. 编写CI4授权接口

在CI4中创建AuthController控制器,新增权限校验方法:

<?php

namespace App\Controllers;

use CodeIgniter\Controller;

class AuthController extends Controller
{
    public function checkAccess()
    {
        // 初始化会话,获取当前登录用户ID
        $session = session();
        $currentUser = $session->get('user_id');

        // 获取Nginx传递的目标文件路径
        $targetPath = $_SERVER['HTTP_X_TARGET_PATH'] ?? '';

        // 从路径中提取用户目录(如从/files/user1/img/foo.jpg中拿到user1)
        preg_match('#^/files/([^/]+)/#', $targetPath, $matches);
        $targetUser = $matches[1] ?? '';

        // 权限校验:当前用户匹配目标目录+文件真实存在
        if ($currentUser === $targetUser && file_exists(FCPATH . $targetPath)) {
            http_response_code(200);
            exit;
        }

        // 权限不足或文件不存在
        http_response_code(403);
        exit;
    }
}

2. 配置Nginx

修改站点配置,添加/files/路径的拦截规则:

server {
    # 原有配置...

    # 拦截用户专属文件请求
    location ^~ /files/ {
        # 检查是否携带CI4会话Cookie(默认ci_session,可根据CI4配置调整)
        if ($http_cookie !~* "ci_session=") {
            return 403;
        }

        # 将目标路径通过HTTP头传给CI4授权接口
        set $target_path $request_uri;
        proxy_set_header X-Target-Path $target_path;

        # 请求CI4授权接口做校验
        auth_request /auth/check-access;

        # 校验通过后直接返回文件
        root /path/to/your/project; # 项目根目录,确保/files在该路径下
        try_files $uri =404;
    }

    # 授权接口的FastCGI转发(和原有CI4的PHP配置一致)
    location = /auth/check-access {
        internal; # 禁止外部直接访问,仅允许内部请求
        fastcgi_pass unix:/run/php/php8.2-fpm.sock; # 根据你的PHP版本调整
        fastcgi_param SCRIPT_FILENAME $document_root/index.php;
        fastcgi_param PATH_INFO /Auth/checkAccess; # 对应CI4控制器方法路径
        include fastcgi_params;
    }
}

方案二:签名URL(适合临时访问场景)

由CI4生成带签名的临时URL,Nginx验证签名通过后返回文件,适合需要给用户开放短期访问权限的场景。

1. CI4生成签名URL

新增签名工具类:

<?php

namespace App\Libraries;

class SignedUrl
{
    private $secretKey = 'your-strong-secret-key'; // 替换为你的保密密钥

    public function generate(string $filePath, int $expireSeconds = 3600): string
    {
        $expire = time() + $expireSeconds;
        $currentUser = session()->get('user_id');
        // 签名内容:用户ID+文件路径+过期时间
        $signData = $currentUser . '|' . $filePath . '|' . $expire;
        $signature = hash_hmac('sha256', $signData, $this->secretKey);

        // 拼接带参数的URL
        return $filePath . '?sign=' . $signature . '&expire=' . $expire . '&user=' . $currentUser;
    }
}

在控制器中调用生成签名URL:

$signedUrl = new \App\Libraries\SignedUrl();
$userFileUrl = $signedUrl->generate('/files/user1/img/foo.jpg');

2. Nginx配置(需安装ngx_http_lua_module)

server {
    # 原有配置...

    location ^~ /files/ {
        root /path/to/your/project;

        access_by_lua_block {
            local secret_key = "your-strong-secret-key" # 和CI4中的密钥保持一致
            local args = ngx.req.get_uri_args()
            local sign = args.sign or ""
            local expire = tonumber(args.expire) or 0
            local user = args.user or ""
            local file_path = ngx.var.uri

            # 检查参数完整性
            if sign == "" or expire == 0 or user == "" then
                ngx.exit(403)
            end

            # 检查是否过期
            if os.time() > expire then
                ngx.exit(403)
            end

            # 验证签名
            local sign_data = user .. "|" .. file_path .. "|" .. expire
            local expected_sign = ngx.hmac_sha256(secret_key, sign_data)
            if ngx.encode_base64(expected_sign) ~= sign then # 编码方式需和CI4一致
                ngx.exit(403)
            end

            # 验证用户目录匹配
            local target_user = string.match(file_path, "^/files/([^/]+)/")
            if target_user ~= user then
                ngx.exit(403)
            end
        }

        try_files $uri =404;
    }
}

方案三:内部重定向(简单过渡方案)

用户请求友好URL(如/my-files/img/foo.jpg),Nginx先转发给CI4验证权限,CI4通过后触发内部重定向,让Nginx直接返回真实文件。

1. CI4控制器方法

public function serveFile()
{
    $session = session();
    $currentUser = $session->get('user_id');
    $fileType = $this->request->getGet('type'); // img或pdf
    $fileName = $this->request->getGet('name');

    // 构造真实文件路径
    $realPath = "/files/{$currentUser}/{$fileType}/{$fileName}";
    $fullPath = FCPATH . $realPath;

    if (!file_exists($fullPath)) {
        throw new \CodeIgniter\Exceptions\PageNotFoundException();
    }

    // 发送内部重定向指令给Nginx
    header("X-Accel-Redirect: " . $realPath);
    exit;
}

2. Nginx配置

server {
    # 原有配置...

    # 内部重定向路径,禁止外部直接访问
    location ^~ /files/ {
        internal;
        root /path/to/your/project;
    }

    # 用户访问的友好路径
    location /my-files/ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root/index.php;
        fastcgi_param PATH_INFO /Auth/serveFile;
        include fastcgi_params;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:55:19