質問

I'm using Silex/Symfony 2 framework. Users may upload either private (web/assets/uploads/*.*) and public documents (app/uploads/*.*), uploaded file is moved to the right folder with a sanitized name, and a new record is created in the upload table.

+-app/
| +-.htaccess                 <-- Deny from all
| +-uploads/                  <-- private upload folder
|   +-private_upload.pdf      <-- private document
+-web/
  +-index.php                 <-- front controller
  +-assets/
  | +-img/
  | +-css/
  | +-js/
  | +-uploads/                <-- public upload folder
        +-public_document.pdf <-- public document

Assets like images and css uploads should be served as usual, i.e. a direct link to the filename:

<img src="/web/assets/img/logo.png" />

Apache configuration idea (production environment)

Files in private or public upload folders should be served using a controller for getting the sanitized name and checking permissions.

Right now all requests (for files that don't exist) passes through the front controller index.php:

<IfModule mod_rewrite.c>
    Options -MultiViews

    RewriteEngine On
    RewriteBase /web
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [QSA,L]
</IfModule>

Requests for app/* are denied using .htaccess file. Is this correct and safe?

PHP 5.4 Web Server issue (development environment)

In my index.php I've the following code:

$filename = __DIR__.preg_replace('#(\?.*)$#', '', $_SERVER['REQUEST_URI']);

if (php_sapi_name() === 'cli-server' && is_file($filename)) {
    return false;
}

If a request is for a filename and (the file actually exists) index.php returns false, allowing the PHP 5.4 Web Server to serve the file statically.

The problem is that those lines won't allow me to catch routes like /files/private_document.pdf, managed with my FilesController class:

$controllers->get('/files/{file}', 'file_controller:serveAction')
    ->assert('file', '.*')
    ->bind('file_serve');
役に立ちましたか?

解決

if(php_sapi_name() === 'cli-server') {
    if(is_file(__DIR__.preg_replace('#(\?.*)$#', '', $_SERVER['REQUEST_URI']))) {
        return false;
    }
}

The solution for PHP 5.4 web server, along with starting the server itself with:

php -S localhost: 80 -t /path/to/web /path/to/web/index.php

This way, if /css/style.css exists it will be served statically, but /files/dynamic.css will pass through the front controller.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top