Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP and MySQL - how to avoid password in source code? [duplicate]

The easiest way is, like you said, to use a configuration file.

Many frameworks use this (Zend, CakePHP, Kohana, etc) and it's the most common way of doing things (even in a non-PHP environment such as ASP.NET with its web.config files). This allows you also to copy over configuration values from environment to environment by just copying the files for the site, which is a benefit over relying on server-setup environment variables (which can very quickly be lost and forgotten).

You shouldn't need to worry about obfuscation of the password since it's not a world-accessible file, it certainly shouldn't be web accessible. What I mean by this is that you would either a) Tell your web server not to serve your configuration file (IIS already does this with web.config files and serves a HTTP 404.8 status instead of the contents) or b) Move it outside of your web served directory. If somebody can see your configuration file, it's worse than having it in your source code.

It's also going to be a good idea to have a base (empty / default) version of the configuration file, and separate it out per environments, so that you could have a different configuration file for production, development, and testing platforms.

An environment variable is the most common way to differentiate between these environments, something like the below code:

// Check if it's been set by the web server
if (!empty($_ENV['ENVIRONMENT'])) {
    // Copy from web server to PHP constant
    define('ENVIRONMENT', $_ENV['ENVIRONMENT']);
}

if (!defined('ENVIRONMENT')) {
    // Default to development
    define('ENVIRONMENT', 'development');
}

// Load in default configuration values
require_once 'config.default.php';

// Load in the overridden configuration file for this environment
require_once 'config.' . ENVIRONMENT . '.php';

Another way that is pretty common is to use an XML configuration file and only read in the values that you need as appropriate (storing a cached copy of the config file in memory). This can very easily be restricted to only load in certain values, rather than allowing arbitrary inclusion of PHP files and is overall a better solution in my opinion, but the above should get you started in the right direction.

You'll probably want your VCS to ignore the file. On the other hand, you might want a skeleton of the file, or one with reasonable defaults (the latter does not apply to login data, of course), to be version controlled. A common way to deal with that is to have a checked-in template configuration file, and the installation procedure copies that file to the location of the real configuration file, where it is customized. This can be a manual, or an automated, process.

(Whilst somewhat unrelated to the main question, introducing a constant for your environment allows you to do some other cool stuff like deferring to a fake mail implementation instead of a live SMTP one, but of course this could also be done with a configuration file)


One pretty nice solution, if you are on Apache, it to store the information in the virtualhost configuration

SetEnv  MYSQL_USER     "xx"
SetEnv  MYSQL_PASSWORD "y2wrg435yw8"

The data can easily be fetched using $_ENV[] for use in the code.


As others have mentioned, put it in a separate configuration file outside of source control (obviously this will be mentioned in code which is under source control).

It also is a good idea to name the file config.php rather than config.ini in case the directory is ever accidentally exposed, meaning that the file won't be downloaded, rather it returns nothing.


If you feel that the 12factor way is valuable, they recommend storing config in the environment.

This has the added advantage of allowing you to write the exact same code when you're testing or otherwise in a non-production environment. If you want (or need) to change the database, or anything else, there's no need to modify your code - you just change the environment variables and you're good to go.


What I would do is to store only example config file in repository, like config.php.dist and don't put actual config.php under version control.


Good question. You could move the most sensitive pieces (e.g. keys/passwords) out as environment variables, but that would then just defer the problem to your server configuration (Which presumably is also in a repository).

You could also try to avoid passwords for stuff like the database, by making it password less and secure it behind a firewall instead. None of these are perfect solutions, but they are the approaches that I know about.