PHP и MySQL - как избежать пароля в исходном коде?

У меня есть небольшое приложение PHP, хранящее данные в базе данных MySQL. В настоящее время имя пользователя/пароль жестко закодированы в PHP-коде. Ситуация, которая мне не очень нравится, например, поскольку код также доступен в репозитории.

Лучшая идея - перенести данные из кода в файл конфигурации (исключенный из репозитория) и каким-то образом закодировать его, поэтому он не читается напрямую (обфускация). Есть ли лучший и простой способ решения проблемы?

$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) { 
    die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');

Сфера применения: Я хочу создать надежное, но также удобное в использовании решение. Я хочу разумную безопасность, но здесь я не имею конфиденциальных данных.

Примечание. Больше не рекомендуется использовать функции mysql_connect, см. вопрос о переполнении стека Почему бы мне не использовать функции mysql_ в PHP? *. Я мог бы изменить пример кода, но поскольку некоторые комментарии относятся к этому, я этого не делал. Однако первоначальный характер вопроса остается в силе.

Ответ 1

Самый простой способ, как вы сказали, - использовать файл конфигурации.

Многие фреймворки используют это (Zend, CakePHP, Kohana и т.д.), и это самый распространенный способ делать вещи (даже в среде, отличной от PHP, такой как ASP.NET с файлами web.config). Это позволяет также копировать значения конфигурации из среды в окружающую среду, просто скопировав файлы для сайта, что является преимуществом, полагаясь на переменные среды настройки сервера (которые очень быстро могут быть потеряны и забыты).

Вам не нужно беспокоиться о запутывании пароля, так как он не является всемирно доступным файлом, он, конечно же, не должен быть доступен в Интернете. Что я имею в виду, так это то, что вы либо a) скажете, что ваш веб-сервер не служит вашему конфигурационному файлу (IIS уже делает это с web.config файлами и обслуживает HTTP 404.8 вместо содержимого) или b) Переместите его за пределы вашего веб-каталога. Если кто-то может видеть ваш файл конфигурации, это хуже, чем в исходном коде.

Также будет хорошей идеей иметь базовую (пустую/стандартную) версию файла конфигурации и разделить ее на среду, чтобы у вас мог быть другой файл конфигурации для платформ производства, разработки и тестирования.

Переменная окружения - наиболее распространенный способ разграничения между этими средами, что-то вроде кода ниже:

// Check if it 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';

Другим способом, который довольно распространен, является использование файла конфигурации XML и чтение только необходимых значений (сохранение кэшированной копии файла конфигурации в памяти). Это можно легко ограничить только загрузкой определенных значений, а не разрешать произвольное включение файлов PHP и, в целом, лучшее решение, на мой взгляд, но выше, чтобы вы начали в правильном направлении.

Вероятно, вы захотите, чтобы ваш VCS проигнорировал файл. С другой стороны, вам может понадобиться скелет файла или один с разумными значениями по умолчанию (последний, конечно, не относится к данным для входа), чтобы управлять версией. Общим способом борьбы с этим является наличие зарегистрированного файла конфигурации шаблона, и процедура установки копирует этот файл в место реального файла конфигурации, где он настроен. Это может быть ручной или автоматический процесс.

(В то время как несколько не связанный с основным вопросом, введение константы для вашей среды позволяет вам делать некоторые другие интересные вещи, такие как перенос на фальшивую почтовую реализацию вместо живого SMTP один, но, конечно, это также можно сделать с конфигурационным файлом)

Ответ 2

Одно довольно приятное решение, если вы находитесь в Apache, чтобы сохранить информацию в конфигурации виртуального хоста

SetEnv  MYSQL_USER     "xx"
SetEnv  MYSQL_PASSWORD "y2wrg435yw8"

Данные можно легко извлечь, используя $_ENV[] для использования в коде.

Ответ 3

Как уже упоминалось, поставьте его в отдельный файл конфигурации вне исходного кода (очевидно, это будет упомянуто в коде, который находится под контролем источника).

Также неплохо было бы назвать файл config.php, а не config.ini, если каталог случайно не обнаружен, что означает, что файл не будет загружен, а он ничего не вернет.

Ответ 4

Если вы считаете, что метод 12factor является ценным, он рекомендует сохранять конфигурацию в среде.

Это дает дополнительное преимущество, позволяя вам писать точный код при тестировании или иным образом в непроизводственной среде. Если вы хотите (или нуждаетесь) изменить базу данных или что-то еще, вам не нужно изменять код - вы просто изменяете переменные среды, и вам хорошо идти.

Ответ 5

Что бы я сделал, это хранить только файл конфигурации примера в репозитории, например config.php.dist, и не устанавливать фактический файл config.php под управлением версии.

Ответ 6

Рекомендуется переместить пароль из кода в файл конфигурации, поэтому пароль не будет находиться в репозитории. Идея зашифровать его в файле конфигурации сомнительна, потому что тот, у кого есть файл конфигурации + PHP-код, который расшифровывает его, всегда может запускать код и получать пароль с четким текстом. Вероятно, было бы лучше сохранить пароль в файле конфигурации как обычный текст и подумать, как защитить файл конфигурации от несанкционированного доступа.

Ответ 7

Хороший вопрос. Вы можете переместить наиболее чувствительные элементы (например, ключи/пароли) в качестве переменных окружения, но тогда это просто отложит проблему до конфигурации вашего сервера (что, предположительно, также находится в репозитории).

Вы также можете попытаться избежать паролей для таких вещей, как база данных, уменьшив пароль и закрепив его за брандмауэром. Ни одно из них не является идеальным решением, но они являются подходами, о которых я знаю.

Ответ 8

Вы всегда можете создать конфигурационный файл ini с помощью функции parse_ini_file.

Ответ 9

Я не вижу здесь всей этой проблемы. Если вы используете репозиторий, вам, вероятно, не нужны жесткие пароли и конфигурация. Вместо этого вы должны указать по умолчанию:

host: localhost
user: root
pass: root
name: db

Если вы действительно хотите, вы можете использовать и анализировать файл .ini, но он может быть очень медленным по сравнению с массивом, установленным в исходном коде, и на самом деле не имеет для меня такого смысла.

Помните: единственное, чему вы можете доверять, это ваш исходный код, если они могут его получить, вы все равно ввернуты.