web-dev-qa-db-fra.com

PHP et MySQL - comment éviter le mot de passe dans le code source?

J'ai une petite application PHP stockant des données dans une base de données MySQL . Actuellement, le nom d'utilisateur/mot de passe est codé en dur dans le code PHP Une situation que je n'aime pas vraiment, par exemple, car le code est également disponible dans un référentiel.

La meilleure idée que j'ai est de déplacer les données du code vers un fichier de configuration (exclus du référentiel), et de les encoder d'une manière ou d'une autre, donc elles ne sont pas directement lisibles (obscurcissement). Existe-t-il un moyen meilleur et facile à utiliser pour résoudre le problème?

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

Périmètre: je souhaite mettre en place une solution robuste, mais aussi simple d'utilisation. Je veux une sécurité raisonnable, mais je ne traite pas ici de données hautement confidentielles.

Remarque: il n'est plus recommandé d'utiliser le mysql_connect fonctions, voir Stack Overflow question Pourquoi ne devrais-je pas utiliser mysql _ en PHP? *. J'aurais pu changer l'exemple de code, mais comme certains commentaires s'y réfèrent, je ne l'ai pas fait. Cependant, la nature originale de la question reste valable.

111
Horst Walter

Le moyen le plus simple est, comme vous l'avez dit, d'utiliser un fichier de configuration.

De nombreux frameworks utilisent cela ( Zend , CakePHP , Kohana , etc.) et c'est la façon la plus courante de faire les choses (même dans un environnement non PHP comme ASP.NET avec son web.config des dossiers). Cela vous permet également de copier les valeurs de configuration d'un environnement à l'autre en copiant simplement les fichiers pour le site, ce qui est un avantage par rapport à la dépendance aux variables d'environnement de configuration du serveur (qui peuvent très rapidement être perdues et oubliées).

Vous ne devriez pas avoir à vous soucier de l'obscurcissement du mot de passe car ce n'est pas un fichier accessible à tous, il ne devrait certainement pas être accessible sur le Web. Ce que je veux dire par là, c'est que vous: a) Dites à votre serveur Web de ne pas servir votre fichier de configuration ( IIS le fait déjà avec web.config fichiers et sert un état HTTP 404.8 au lieu du contenu) ou b) Déplacez-le en dehors de votre répertoire Web servi. Si quelqu'un peut voir votre fichier de configuration, c'est pire que de l'avoir dans votre code source.

Ce sera également une bonne idée d'avoir une version de base (vide/par défaut) du fichier de configuration et de le séparer par environnement, afin que vous puissiez avoir un fichier de configuration différent pour les plates-formes de production, de développement et de test.

Une variable d'environnement est le moyen le plus courant de différencier ces environnements, quelque chose comme le code ci-dessous:

// 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';

Une autre méthode assez courante consiste à utiliser un fichier de configuration XML et à ne lire que les valeurs dont vous avez besoin (en stockant une copie mise en cache du fichier de configuration en mémoire). Cela peut très facilement être limité à seulement charger dans certaines valeurs, plutôt que de permettre l'inclusion arbitraire de fichiers PHP et est globalement une meilleure solution à mon avis, mais ce qui précède devrait vous aider à démarrer dans la bonne direction) direction.

Vous voudrez probablement que votre VCS ignore le fichier. D'un autre côté, vous pouvez souhaiter qu'un squelette du fichier, ou un avec des valeurs par défaut raisonnables (ce dernier ne s'applique pas aux données de connexion, bien sûr), soit contrôlé par la version. Un moyen courant de résoudre ce problème consiste à disposer d'un fichier de configuration de modèle archivé, et la procédure d'installation copie ce fichier à l'emplacement du fichier de configuration réel, où il est personnalisé. Il peut s'agir d'un processus manuel ou automatisé.

(Bien que quelque peu sans rapport avec la question principale, l'introduction d'une constante pour votre environnement vous permet de faire d'autres trucs sympas comme reporter à une implémentation de faux courrier au lieu d'un live SMTP un, mais bien sûr, cela pourrait aussi être fait avec un fichier de configuration)

68
Rudi Visser

Une jolie solution sympa, si vous êtes sur Apache, c'est de stocker les informations dans la configuration de l'hôte virtuel

SetEnv  MYSQL_USER     "xx"
SetEnv  MYSQL_PASSWORD "y2wrg435yw8"

Les données peuvent être facilement récupérées à l'aide de $_ENV[] à utiliser dans le code.

46
hank

Comme d'autres l'ont mentionné, placez-le dans un fichier de configuration séparé en dehors du contrôle de code source (cela sera évidemment mentionné dans le code qui est sous contrôle de code source).

C'est aussi une bonne idée de nommer le fichier config.php plutôt que config.ini au cas où le répertoire serait accidentellement exposé, ce qui signifie que le fichier ne sera pas téléchargé , il ne renvoie rien.

11
acutesoftware

Si vous pensez que la méthode 12factor est précieuse, ils recommandent de stocker la configuration dans l'environnement.

Cela a l'avantage supplémentaire de vous permettre d'écrire exactement le même code lorsque vous testez ou autrement dans un environnement de non-production. Si vous voulez (ou avez besoin) de changer la base de données, ou quoi que ce soit d'autre, il n'est pas nécessaire de modifier votre code - vous changez simplement les variables d'environnement et vous êtes prêt à partir.

5
Wayne Werner

Ce que je ferais, c'est de stocker uniquement un exemple de fichier de configuration dans le référentiel, comme config.php.dist et de ne pas mettre config.php réel sous contrôle de version.

2
Serge Kuharev

C'est une bonne idée de déplacer le mot de passe du code vers un fichier de configuration, afin que le mot de passe ne soit pas dans le référentiel. L'idée de le chiffrer dans un fichier de configuration est discutable, car celui qui a le fichier de configuration + PHP code qui le déchiffre peut toujours exécuter le code et obtenir un mot de passe en texte clair. Probablement il serait préférable de conserver le mot de passe dans un fichier de configuration sous forme de texte brut et de penser comment protéger le fichier de configuration contre tout accès non autorisé.

2
Mikhail Vladimirov

Bonne question. Vous pouvez déplacer les éléments les plus sensibles (par exemple, clés/mots de passe) en tant que variables d'environnement, mais cela ne ferait que reporter le problème à la configuration de votre serveur (qui se trouve probablement également dans un référentiel).

Vous pouvez également essayer d'éviter les mots de passe pour des choses comme la base de données, en le rendant moins mot de passe et en le sécurisant derrière un pare-feu à la place. Aucune de ces solutions n'est parfaite, mais ce sont les approches que je connais.

2
troelskn

Je ne vois pas tout ce problème ici. Si vous partagez un référentiel, vous ne voudrez probablement pas coder en dur les mots de passe et la configuration. Vous devez en fournir une par défaut:

Host: localhost
user: root
pass: root
name: db

Si vous voulez vraiment, vous pouvez utiliser et analyser un .ini mais il est probable qu'il soit très lent par rapport à un tableau défini dans le code source et n'a pas vraiment de sens pour moi.

Rappelez-vous: la seule chose à laquelle vous pouvez faire confiance est votre code source, s'ils peuvent l'obtenir, vous êtes quand même foutu.

1
Shoe

Vous pouvez toujours créer un fichier de configuration ini en utilisant la fonction parse_ini_file.

1
Dawid Sajdak