On hiding the main Symfony front controller
Published on 2019-08-23 • Modified on 2024-11-10
In this post, we will see how to hide the front controller's file name of a Symfony application so it can't be accessed when typing it: "index.php". The less the users (or hackers of course) will know about the technical implementation of your website, the better it is. Let's go! 😎
It's the summer so this post will be very light. It's a test I have done on this blog. I wanted to have a specific controller for the production environment (like with Symfony3) and to hide the main controller so typing "/index.php" will give a 404 error without using a .htaccess
file nor redirections (when using Apache as the webserver). It's not considered as a good practice, so use at your own risk!
» Published in "A week of Symfony 661" (26 August - 1 September 2019).
Configuration
- PHP 8.4
- Symfony 6.4
- Apache 2.4
Introduction
The main front controller is the file that handles all HTTP requests of a Symfony application. When using Symfony4 or 5, it's the index.php
file and it's located in the "public" directory. For example, when accessing the official Symfony website, you will notice that these URLs are available: (it has been fixed since the writing of this blog post in 2019)
- https://symfony.com
- https://symfony.com/index.php
- https://symfony.com/blog/
- https://symfony.com/index.php/blog/
The goal here will be to prevent the users, bots or search indexes to access URLs through the index.php
file.
Creation of a specific production front controller
Add a file in the "public" folder of your application and name it with a random string. (eg: ajJoNGJix4KRMM3xwhgLXG4GUgJHhyFk.php
) Add the following code:
<?php
// public/ajJoNGJix4KRMM3xwhgLXG4GUgJHhyFk.php
// this is a fake name, not the one used by this website! 😁
declare(strict_types=1);
// PHP 8.4 local
if (PHP_VERSION_ID >= 80401) {
error_reporting(E_ALL & ~E_DEPRECATED);
}
use App\Kernel;
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return static fn (array $context) => new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
We have removed all dev and debug stuff to keep only the minimum code. (the performance difference with the default index.php
isn't substantial) And we still have our index.php
, I have renamed it to index_dev.php
in this project but it's Ok to keep the original name.
Be careful that if you set TRUSTED_PROXIES
or TRUSTED_HOSTS
environment variables, you should keep the following lines:
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) {
Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
}
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
Request::setTrustedHosts(explode(',', $trustedHosts));
}
Hiding the main front controller name
Now, let's hide the main controller. The first thing is to exclude the index.php
file from your deployment process. To deploy this blog I use EasyDeploy, you will find my deploy file here. I delete the index_dev.php
file with the controllersToRemove()
function. Now, we have to tell our webserver to use the new file, for example when using Apache:
# https://stackoverflow.com/questions/59921221/apache-how-to-handle-unknown-php-file-like-standard-urls
# configuration/vhosts/prod/www.strangebuzz.com-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName www.strangebuzz.com
ServerAlias strangebuzz.com
DocumentRoot /var/www-protected/strangebuzz.com/public
DirectoryIndex /ajJoNGJix4KRMM3xwhgLXG4GUgJHhyFk.php
<Directory /var/www-protected/strangebuzz.com/public>
AllowOverride All
Require all granted
# this is a fake one, again! 😁
FallbackResource /ajJoNGJix4KRMM3xwhgLXG4GUgJHhyFk.php
#FallbackResource /index.php
# 1st test to move .htaccess here
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^(.*)index.php$ /$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /ajJoNGJix4KRMM3xwhgLXG4GUgJHhyFk.php [L]
</Directory>
ErrorDocument 404 https://www.strangebuzz.com/404
ErrorLog /var/log/apache2/strangebuzz.com_error.log
CustomLog /var/log/apache2/strangebuzz.com_access.log combined
SSLCertificateFile /etc/letsencrypt/live/strangebuzz.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/strangebuzz.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
# . to www
RewriteEngine on
RewriteCond %{SERVER_NAME} =strangebuzz.com
RewriteRule ^ https://www.strangebuzz.com [END,NE,R=permanent]
</VirtualHost>
</IfModule>
# Used as full snippet in templates/blog/posts/_39.html.twig
As you can see, we have modified the fallback resource to be our new production controller instead of index.php
. Et voilà! Now, when accessing /index.php
, we get a 404 so there is only one URL associated with each resource. And the canonical URL will always be the version without the file inside.
Bonus:
1) There is a post in this blog where you could find the real main controller file name of this website, can you find it?
2) Why is it still indicated index.php
?
Click here to see the answers!
1) It's here: The Symfony Request class interactive cheatsheet. The main front controller file name is returned by the getScriptName()
function of the Request value object.
2) I am cheating, I simply put index.php
manually instead of getting the result of the function! 😁
[
'name' => 'getScriptName',
'parameters' => '',
'type' => 'string',
//'result' => $r->getScriptName(),
'result' => 'index.php', // hide real controller name
'show' => !$refresh,
'url' => 812
],
That's it! I hope you like it. Check out the links below to have additional information related to the post. As always, feedback, likes and retweets are welcome. (see the box below) See you! COil. 😊
The Symfony doc More on Stackoverflow More on the web
Call to action
Did you like this post? You can help me back in several ways: (use the "reply" link on the right to comment or to contact me )
- Report any error/typo.
- Report something that could be improved.
- Like and repost!
- Follow me on Bluesky 🦋
- Subscribe to the RSS feed.
- Click on the More on Stackoverflow buttons to make me win "Announcer" badges 🏅.
Thank you for reading! And see you soon on Strangebuzz! 😉