访问webroot之外但仍在应用程序路径中的文件夹/文件?

时间:2013-09-25 23:08:56

标签: cakephp file-access

我的网站应用中有一个文件夹data,该文件夹不在网络根目录中。这样做是为了提高安全性,因此只有某些人才能访问它。我查看CakePHP文档时使用的代码如下:

foreach($ImageToSort as $FileDisplayKey => $FileDisplayData) {
    $FileName = $ImageToSort[$FileDisplayKey]['Fileinfo']['filename'];
    $WholePathName = 'data/'.$FileName;
}

$this->response->file($WholePathName);
return $this->response;

它加载文件但不在我的视图中(上面的代码在视图中,$ImageToSort是从我的Controller中的查找调用设置的)。

那么如何通过某种循环加载不在webroot中的文件,以便我可以查看它们并按照我选择的方式将它们放在我的网站上?

PS。我不能把文件放在webroot文件夹中,因为有人只需知道文件的名称就可以获得它。访问这些文件需要保留给少数人。

非常感谢你给予的任何帮助,

格伦

更新

我正在使用2.4,从我读到的媒体视图不是我应该使用的,但'发送文件'是已经取代它们的调用。我尝试使用以下代码:

$this->viewClass = 'Media';

$params = array(
    'id'        => $FileName,
    'name'      => 'example',
    'extension' => 'jpg',
    'path'      => APP . 'uploads/test' . DS
);

$this->set($params);

debug($params['id']);
$name = $params['id'];
$path = $params['path'];
$filename = $path.$name;


//echo 'name::' .$name;
echo "<img src=";
echo $filename;
echo ">";

除非我将文件放入/webroot/data/test,否则无法找到该文件,然后显示正常。但这完全没有意义?我只需要选择用户来查看所选文件的安全问题。

以下代码可用于查看/app/data/test路径中的文件

$this->autoRender = false;
$this->response->file(Configure::read('uploads').$WholePathName);

但是这个代码在控制器或视图中使用时没有任何区别,它仍然只显示文件,没有布局或样式或标题或任何东西。再一次,这完全没有意义。

必须有一种方法可以让我的文件访问并读取我需要的文件/文件夹。

格伦

1 个答案:

答案 0 :(得分:1)

创建一个适当的控制器/动作,它接受一个路径片段(例如通过查询传递),检查是否允许当前用户访问文件,将路径片段与基本路径组合并输出文件内容。

然后在视图中使用img元素src属性的相应网址,例如

<img src='/files/read/?file=foo/bar.jpg'>

这样只有授权用户才能访问您的文件。

这是一个非常基本的控制器/操作示例,如果不允许用户访问文件,则使用401进行响应;如果找不到文件,则使用404进行响应,不是文件或不在基本路径内,万一一切都很好,它提供文件:

class FilesController extends AppController
{
    public function read()
    {
        // you'd probably use auth component checks and stuff here
        if(testWhetherUserIsAllowedToAccessFiles() !== true)
        {
            throw new ForbiddenException();
        }

        // make sure that the base path points to a folder that only
        // holds the files that should be accessible!
        $base = ROOT . DS . 'files' . DS;
        $fragment = $this->request->query('file');

        // expand to a canonicalized absolute path, it's way easier to
        // test for validity using the real path
        $path = realpath($base . $fragment);

        // just a basic sanity check, you may want to implement some more
        // security checks to make sure there's really no way to access
        // files outside of the base directory! After all this is just
        // some example code.
        if(
            !!preg_match('~\.\.(\\\\|/)~', $fragment) ||
            $path === false || !is_file($path) ||
            mb_strpos($path, $base) !== 0)
        {
            throw new NotFoundException();
        }

        $this->response->file($base . $fragment);
        return $this->response;
    }
}

从CakePHP 2.4.8开始,响应对象检查可能的路径遍历片段,因此理论上,如果没有通过,则不需要此示例中的附加检查扩展的真实路径,但原始的,连接的路径!