Installation et Utilisation d'un serveur Apache, Base de Données Mysql, PHP 4 et phpMyAdmin.

Yann MORÈRE

Décembre 2001-Juillet 2002

Contents

1  Introduction
2  Installation de la base de données MySQL
3  Configuration et Installation de PHP 4
    3.1  Compilation en module statique d'apache
    3.2  Compilation en module dynamique d'apache
4  Configuration et Installation du serveur HTTP Apache
    4.1  Compilation en module statique d'apache
    4.2  Configuration du serveur HTTP Apache
5  Mise à jour de la version de PHP
    5.1  Mise à jour de la version statique
    5.2  Mise à jour de la version dynamique
6  Jouons avec les bases de données
7  Installation de phpMyAdmin
    7.1  Installation
        7.1.1  Installation Rapide
        7.1.2  Mettre à jour à partir d'un version plus ancienne
8  Sécurisation de votre installation Web
    8.1  Sécurisation d'Apache
        8.1.1  Protection par .htaccess
        8.1.2  Protection par modification de httpd.conf
        8.1.3  Différence entre les deux méthodes .htaccess et httpd.conf
        8.1.4  Protection de fichiers particuliers dans un sous répertoire
        8.1.5  Rendre le contenu d'un sous-répertoire invisible
    8.2  Sécurisation de Mysql
        8.2.1  Configuration des fichiers d'autorisations d'accès
        8.2.2  Automatisation des connexions
        8.2.3  Contrôle des accès MySQL initiés par des scripts PHP
    8.3  Sécurisation de PHPMyAdmin
        8.3.1  Configuration avec adv_auth = false
        8.3.2  Configuration avec adv_auth=true
        8.3.3  Les modes auth_type= http, cookie et config
        8.3.4  Exemple de configuration avec http
    8.4  Le petit bréviaire
    8.5  Conclusion
9  PHP et MySQL
    9.1  Connection à la base
    9.2  Première requète
10  Formulaire, PHP et Mysql

Important

L'article qui suit montre une installation avec une version d'apache qui possède un trou de sécurité par déni de service (découvert en juin 2002). J'ai bien sur testé l'installation avec une version sécurisée (apache 1.3.26) en utilisant la méthode décrite dans les pages suivantes. Tout fonctionne comme prévu mais je n'ai pas réécrit le papier. vous n'aurez qu'à lire 1.3.26 à la place de 1.3.22 pour apache, 4.2.1 à la place de 4.0.1 pour Php.

1  Introduction

Internet a connu une grande mutation ces dernières années. L'apparition des technologies de scripts a permis le passage des pages HTML statiques aux présentations dynamiques et interactives.
PHP est un langage de script coté serveur. Il permet d'ajouter de nouvelles fonctionnalités aux pages Web. En effet, de nos jours un site web doit contenir de nombreuses informations ainsi qu'une bonne présentation. C'est pour cela qu'un site clair et dynamique assure de nombreux avantages aux utilisateurs et aux webmestres.
Un site Web moderne constitue également un moyen de stocker des données et des méthodes de recherche (association avec une base de données SQL par exemple), de traiter des requêtes et de fournir en retour l'information attendue par l'utilisateur.
Et tout ceci doit bien entendu être transparent vis à vis des modifications et évolutions techniques.

Nous allons voir comment mettre en place une version de PHP, qui fonctionne avec la base de données MySQL, tout ceci sous l'égide d'un serveur HTTP Apache.
Comme tout bon linuxien acharné, nous partirons des distributions sources de ces différents logiciels.
Afin de pouvoir utiliser PHP avec une base de données, nous allons commencer par installer MySQL.

2  Installation de la base de données MySQL

La version actuelle de MySQL (au moment de l'écriture de cet article est 3.23.46). C'est avec cette version que nous allons effectuer l'installation. Vous pouvez aussi vous procurer la dernière version directement sur le site http://www.mysql.com.

Afin de pouvoir compiler MySQL vous avez besoin d'un système Unix possédant les outils de développement de base (gcc, make, autoconf, automake...) ainsi que les droits d'écriture sur les répertoires cibles. L'installation décrite ici a été testée sur une FreeBSD 4.2 I386, une Debian 2.2r4 I386, une Debian 2.2r3 Sparc et une Suse 6.3 I386.

Les commandes suivantes devraient suffire à l'installation.

yann@yoda:~/temp$tar xzf mysql-3.23.46.tar.gz
yann@yoda:~/temp$ cd mysql-3.23.46
yann@yoda:~/temp/mysql-3.23.46$ ./configure --prefix=/usr/local/mysql
yann@yann@yoda:~/temp/mysql-3.23.46$ make
yoda:~/temp/mysql-3.23.46$ make test
yann@yoda:~/temp/mysql-3.23.46$ su
Password:
root@yoda:/home/yann/temp/mysql-3.23.46#make install

Entre le make et le make test, vous aurez largement le temps de prendre un café. Vous pouvez aussi en profiter pour faire autre chose sur la machine, car Unix est un système multitâche.

Ceci devrait suffire pour installer MySQL sur votre machine.

Note :   Si vous êtes sous GNU/Linux et que vous utilisez des librairies partagées, assurez vous que ces librairies sont accessibles. Pour cela le fichier /etc/ld.so.conf doit contenir le chemin du répertoire ou se trouve les librairies de MySQL. Par exemple si la librairie MySQL se trouve dans :
/usr/local/mysql/lib/mysql/libmysqlclient.so, assurez vous d'avoir la ligne suivante dans le fichier /etc/ld.so.conf :
/usr/local/mysql/lib/mysql
Sinon éditer le fichier (en tant que root) et ajouter la. Ensuite exécuter la commande /sbin/ldconfig pour remettre à jour la bibliothèque de librairies partagées.

Pour des raisons de sécurité, il est important de dédier un compte à l'usage de la base de données. Pour cela vous pouvez définir un utilisateur spécifique mysql.

Ces commandes ajoutent le groupe mysql et l'utilisateur mysql. La syntaxe de la commande d'ajout d'utilisateur peut être différente suivant le système Unix utilisé.

root@yoda:/home/yann/temp/mysql-3.23.46# groupadd mysql
root@yoda:/home/yann/temp/mysql-3.23.46# useradd -g mysql mysql

On peut maintenant lancer le script d'initialisation qui va créer les tables d'allocations de MySQL (opération nécessaire lors d'une première installation).
root@yoda:/home/yann/temp/mysql-3.23.46# scripts/mysql_install_db
Preparing db table
Preparing host table
Preparing user table
Preparing func table
Preparing tables_priv table
Preparing columns_priv table
Installing all prepared tables
011204 19:39:04  /usr/local/mysql/libexec/mysqld: Shutdown Complete
To start mysqld at boot time you have to copy support-files/mysql.server
to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
This is done with:
/usr/local/mysql/bin/mysqladmin -u root -p password 'new-password'
/usr/local/mysql/bin/mysqladmin -u root -h yoda -p password 'new-password'
See the manual for more instructions.

You can start the MySQL daemon with:
cd /usr/local/mysql ; /usr/local/mysql/bin/safe_mysqld &

You can test the MySQL daemon with the benchmarks in the 'sql-bench' directory:
cd sql-bench ; run-all-tests

Please report any problems with the /usr/local/mysql/bin/mysqlbug script!

The latest information about MySQL is available on the web at
http://www.mysql.com
Support MySQL by buying support/licenses at https://order.mysql.com

root@yoda:/home/yann/temp/mysql-3.23.46#

On peut noter que les versions qui précède la 3.22.10 lançaient le serveur MySQL avec mysql_install_db. Mais ceci n'est plus vrai.

Maintenant, on va donner les droits appropriés afin que le nouvel utilisateur mysql puisse gérer la base de données.

root@yoda:/home/yann/temp/mysql-3.23.46# chown -R root /usr/local/mysql
root@yoda:/home/yann/temp/mysql-3.23.46# chown -R mysql /usr/local/mysql/var
root@yoda:/home/yann/temp/mysql-3.23.46# chgrp -R mysql /usr/local/mysql

La première commande change le propriétaire des fichiers, et les attribue à root, la seconde change le propriétaire du répertoire des données de la base et les attribue à notre utilisateur mysql. La dernière modifie le groupe et et l'attribue au groupe mysql.

Maintenant, tout est installé, vous pouvez initialiser et tester votre nouvelle base de données.

root@yoda:/home/yann/temp/mysql-3.23.46# /usr/local/mysql/bin/safe_mysqld --user=mysql &
[1] 27930
root@yoda:/home/yann/temp/mysql-3.23.46# Starting mysqld daemon
with databases from /usr/local/mysql/var
root@yoda:/home/yann/temp/mysql-3.23.46#

Il est aussi possible d'activer la journalisation simple ou avancée en donnant les commandes suivantes :
root@yoda:/home/yann/temp/mysql-3.23.46# /usr/local/mysql/bin/safe_mysqld
--user=mysql --log &

ou encore
root@yoda:/home/yann/temp/mysql-3.23.46# /usr/local/mysql/bin/safe_mysqld
--user=mysql --log-long-format &

On pourra ensuite tester les commandes suivantes afin de vérifier le bon fonctionnement du serveur et de sa configuration.
yann@yoda:~/temp/php-4.0.6$ cd /usr/local/mysql/bin/
yann@yoda:/usr/local/mysql/bin$ ./mysqladmin version
./mysqladmin  Ver 8.23 Distrib 3.23.46, for unknown-linux-gnu on sparc
Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL license

Server version          3.23.46
Protocol version        10
Connection              Localhost via UNIX socket
UNIX socket             /tmp/mysql.sock
Uptime:                 1 hour 13 min 43 sec

Threads: 1  Questions: 1  Slow queries: 0  Opens: 6  Flush tables: 1  Open tables: 0
Queries per second avg: 0.000
yann@yoda:/usr/local/mysql/bin$

et
yann@yoda:~$ ./mysqladmin variables
+---------------------------------+-------------------------------------
| Variable_name                   | Value
+---------------------------------+-------------------------------------
| back_log                        | 50
| basedir                         | /usr/local/mysql/
| binlog_cache_size               | 32768
| character_set                   | latin1
| character_sets                  | latin1 dec8 dos german1 hp8 koi8_ru
......................

Afin de pouvoir démarrer le serveur MySQL au boot de la machine, vous devrez copier le fichier
support-files/mysql.server au bon endroit pour votre système. Pour cela je vous conseille de vous reporter à la documentation de votre système en ce qui concerne le mode de démarrage et d'arrêt.

Ceci n'est qu'un survol et je vous conseille vivement de lire attentivement le fichier INSTALL-SOURCE livré avec la distribution de MySQL.

MySQL est maintenant installée sur votre système. Nous allons maintenant faire quelques configurations, et tester notre base de données.

Pour plus de sécurité, il est préférable de changer le mot de passe de l'utilisateur root, (celui de la BDD et non celui du système). Pour cela on va d'abord se placer dans la peau de l'utilisateur mysql, celui qui aura la charge de la gestion de la base.

yann@yoda:~/temp/mysql-3.23.46$ su mysql
Password:
bash-2.03$ cd /usr/local/mysql/

A partir de maintenant tout ce qui touche à la base se fera sous l'utilisateur mysql (administrateur=root de la base). Pour que ce serveur de base de données soit utile, il est nécessaire de paramétrer deux éléments. Pour ce qui est de la base de données et des tables, c'est votre affaire. Nous, nous allons tout d'abord définir le mot de passe de l'utilisateur root de la base de données. Il est possible de le faire de 3 manières différentes. Voici la première, la plus simple et la plus rapide :
/usr/local/mysql/bin/mysqladmin -u root password votre_mot_de_passe

ou
/usr/local/mysql/bin/mysql -u root mysql
mysql> UPDATE user SET Password=PASSWORD('votre_mot_de_passe');
       WHERE user='root';
mysql> FLUSH PRIVILEGES;

ou encore
/usr/local/mysql/bin/mysql -u root mysql
mysql> SET PASSWORD FOR root=PASSWORD('votre_mot_de_passe');

Maintenant vous pouvez accédez à la base mysql grâce à la commande suivante :

/usr/local/mysql/bin/mysql -u root -p mysql

ou encore
/usr/local/mysql/bin/mysql -u root --password=votre_mot_de_passe_root  mysql

afin d'y faire les changements que vous désirez. Je vous renvoie à la documentation de MySQL pour cela.

Enfin, pour permettre un démarrage et un arrêt facile de la base, si vous n'avez pas décidez de la lancer au boot de la machine, je vous conseil de copier (en tant qu'administrateur de la machine (root=le vrai root)) les fichiers suivants qui se trouvent dans le répertoire support-files de la distribution source, dans le répertoire /usr/local/mysql/bin.

cp mysql.server mysql.server.sh mysql.spec mysql.spec.sh /usr/local/mysql/bin/
chmod 755 mysql.server mysql.server.sh mysql.spec mysql.spec.sh

Ceci vous permettra de démarrer facilement la base (en tant qu'administrateur de la base, ici l'utilisateur mysql) par :
cd /usr/local/mysql/bin
./mysql.server start

Il est aussi possible de la lancer par la commande :
cd /usr/local/mysql
/usr/local/mysql/bin/safe_mysqld &

Voici pour la base de donnée MySQL, bien sur les dernières informations à propos de MySQL sont disponible sur le site http://www.mysql.com. Pour plus d'informations, je vous renvoie aux pages de man ainsi qu'au manuel de MySQL.

3   Configuration et Installation de PHP 4

Dans cette partie nous allons mettre en place une version opérationnelle de PHP pour qu'elle fonctionne avec la base de données MySQL précédemment installée.
Comme précédemment nous partirons de la distribution source. Cette dernière est disponible à l'adresse http://www.php.net. L'installation décrite dans cet article est basée sur la version 4.0.6.

Il n'est pas possible de parler de PHP, sans introduire la notion de serveur HTTP. En effet, PHP ne sert à rien s'il n'est pas couplé à son serveur web. Bien sur il existe de nombreux serveurs web disponibles, mais c'est le serveur Apache que nous utiliserons.

PHP est capable de prendre en charge de nombreux outils et plate-formes. Dans les outils supportés les plus courants, on peut citer :

Il est à noter que PHP peut être compiler comme un interpréteur CGI indépendant, ou bien comme un module Apache. Pour des raisons de performance et de facilité d'utilisation (notamment avec la base de données MySQL) nous utiliserons PHP comme module du serveur web. De même ce module peut être une module statique d'apache ou bien un module dynamique. Nous verrons ici les deux méthodes.

3.1  Compilation en module statique d'apache

Pour cela, il faut disposer de la distribution d'Apache. Elle est disponible à l'adresse suivante http://www.apache.org. L'installation se fera avec la version 1.3.22.

On va commencer par décompresser les distributions.

yann@yoda:~/temp$ tar xzf apache_1.3.22.tar.gz
yann@yoda:~/temp$ tar xzf php-4.0.6.tar.gz

ou encore par
yann@yoda:~/temp$ gzip -cd apache_1.3.22.tar.gz | tar xvf -
yann@yoda:~/temp$ gzip -cd php-4.0.6.tar.gz | tar xvf -

On passe ensuite dans le répertoire d'apache et allons le configurer pour placer :
yann@yoda:~/temp$ cd apache_1.3.22
yann@yoda:~/temp/apache_1.3.22$ ./configure --sysconfdir=/etc/httpd
--datadir=/home/httpd --logfiledir=/var/log/httpd

Nous revenons ensuite dans le répertoire de la distribution de PHP pour le configurer.
yann@yoda:~/temp$ cd php-4.0.6
yann@yoda:~/temp/php-4.0.6$ ./configure --with-mysql
--with-config-file=/etc/httpd --with-apache=../apache_1.3.22
--enable-track-vars

Ici PHP est configuré comme un module d'apache avec le support de la base de données MySQL. De plus les fichiers de configuration seront placés avec ceux d'Apache. -enable-track-vars permet aux variables GPC-GET et POST et autres cookies d'être envoyés au serveur et d'être pistés.

Il ne nous reste plus qu'a compiler PHP et l'installer par les commandes suivantes :

yann@yoda:~/temp/php-4.0.6$ make
yann@yoda:~/temp/php-4.0.6$ su
password :
root@yoda:/home/yann/temp/php-4.0.6# make install

Avant de pouvoir tester notre nouveau module PHP, il est nécessaire d'installer Apache. C'est l'objet de la partie suivante.

3.2  Compilation en module dynamique d'apache

Cette section est directement tirée du fichier INSTALL de la distribution de PHP. Je ne l'ai pas testée personnellement. Alors bonne chance.

On va commencer par décompresser les distributions.

yann@yoda:~/temp$ tar xzf apache_1.3.22.tar.gz
yann@yoda:~/temp$ tar xzf php-4.0.6.tar.gz

ou encore par
yann@yoda:~/temp$ gzip -cd apache_1.3.22.tar.gz | tar xvf -
yann@yoda:~/temp$ gzip -cd php-4.0.6.tar.gz | tar xvf -

On passe ensuite dans le répertoire d'apache et allons le configurer pour placer :
yann@yoda:~/temp$ cd apache_1.3.22
yann@yoda:~/temp/apache_1.3.22$ ./configure --sysconfdir=/etc/httpd
--datadir=/home/httpd --logfiledir=/var/log/httpd

Nous revenons ensuite dans le répertoire de la distribution de PHP pour le configurer. Il vous faut maintenant choisir ls options dont vous aurez besoin. Pour cela un petit ./configure -help fera l'affaire. Les options dont vous avez besoin se trouve dans la dernière section enable et with.
De manière à pouvoir installer PHP comme un module d'Apache 1.3.x, il faut que ce dernier soit installé sur votre machine. Nous allons donc terminer son installation par les commandes suivantes :
yann@yoda:~/temp/apache_1.3.22$ ./configure --sysconfdir=/etc/httpd
--datadir=/home/httpd --logfiledir=/var/log/httpd  --enable-module=so
yann@yoda:~/temp/apache_1.3.22$ make
yann@yoda:~/temp/apache_1.3.22$ su
Password:
root@yoda:/home/yann/temp/apache_1.3.22# make install
make[1]: Leaving directory `/home/yann/temp/apache_1.3.22'
+--------------------------------------------------------+
| You now have successfully built and installed the      |
| Apache 1.3 HTTP server. To verify that Apache actually |
| works correctly you now should first check the         |
| (initially created or preserved) configuration files   |
|                                                        |
|   /etc/httpd/httpd.conf
|                                                        |
| and then you should be able to immediately fire up     |
| Apache the first time by running:                      |
|                                                        |
|   /usr/local/apache/bin/apachectl start
|                                                        |
| Thanks for using Apache.       The Apache Group        |
|                                http://www.apache.org/  |
+--------------------------------------------------------+

Maintenant Apache est installé et l'on peut vérifier que l'objet module est activé par la commande
/usr/local/apache/bin/httpd -l, vous devriez voir apparaître un truc du genre :

yann@Qui-GonJinn:~/temp/apache_1.3.23 > /usr/local/apache/bin/httpd -l
Compiled-in modules:
  http_core.c
  mod_so.c
  mod_env.c
  mod_log_config.c
  mod_mime.c
  mod_negotiation.c
  mod_status.c
  mod_include.c
  mod_autoindex.c
  mod_dir.c
  mod_cgi.c
  mod_asis.c
  mod_imap.c
  mod_actions.c
  mod_userdir.c
  mod_alias.c
  mod_access.c
  mod_auth.c
  mod_setenvif.c
yann@Qui-GonJinn:~/temp/apache_1.3.23 >

Suivant vote configuration vous pouvez en avoir plus ou moins. Mais du moment que mod_so.c est présent, PHP sera content.
Maintenant nous allonc configurer PHP.
yann@yoda:~/temp$ cd php-4.0.6
yann@yoda:~/temp/php-4.0.6$ ./configure --with-mysql --with-apxs
--with-config-file=/etc/httpd --with-apache=../apache_1.3.22

Si le programme configure vous retourne une erreur car il ne trouve pas apxs, vous pouvez recommencer en lui indiquant le chemin complet vers apxs, pour votre configuration :
yann@yoda:~/temp/php-4.0.6$ ./configure --with-mysql
--with-apxs=/usr/local/apache/bin/apxs
--with-config-file=/etc/httpd --with-apache=../apache_1.3.22

Ici comme nous voulons interfacer PHP avec une Base de doonnées MySQL,nous ajoutons -with-mysql. -enable-track-vars permet aux variables GPC-GET et POST et autres cookies d'être envoyés au serveur et d'être pistés.

Il ne nous reste plus qu'a compiler PHP et l'installer par les commandes suivantes :

yann@yoda:~/temp/php-4.0.6$ make
yann@yoda:~/temp/php-4.0.6$ su
password :
root@yoda:/home/yann/temp/php-4.0.6# make install

Maintenant nous allons configurer Apache, afin qu'il reconnaisse votre module PHP. Normalement le make install devrait réaliser la plus grande partie de la configuration. Normalement, il doit éditer le fichier httpd.conf pour activer le module dynamique de PHP. Vérifier donc si la ligne suivante est présente dans votre fichier :

      LoadModule php4_module /usr/local/lib/libphp4.so

Le chemin vers la librairie PHP peut différer suivant votre configuration, vérifier donc que ce chemin pointe bien vers le module.
Si quelque part dans votre fichier httpd.conf, vous avez une ligne ClearModuleList vous devrez alors ajouter la ligne suivante :

      AddModule mod_php4.c

Finalement vous devrez renseigner Apache sur les fichiers qui nécessite PHP (typiquement les fichier .php). Pour cela il vous faut créer un type mime spécial et l'associer à une extension. Voici ce que vous pouvez mettre :
      AddType application/x-httpd-php .php

Enfin il nous faut placer les fichiers de configuration de PHP dans le répertoire de configuration d'Apache. Pour cela on utilise les commande suivantes.

root@yoda:/home/yann/temp/apache_1.3.22# cd ../php-4.0.6
root@yoda:/home/yann/temp/php-4.0.6# cp php.ini-dist /etc/httpd/php.ini

Pour la suite de la configuration d'apache (port, nom de serveur, etc...), je vous renvoie au point suivant (4.2).

4   Configuration et Installation du serveur HTTP Apache

4.1  Compilation en module statique d'apache

Nous allons maintenant reconfigurer Apache afin qu'il prenne en compte le nouveau module PHP fraîchement compilé. Ensuite on peut le compiler et l'installer par les commandes suivantes.
yann@yoda:~/temp/apache_1.3.22$ ./configure --sysconfdir=/etc/httpd
--datadir=/home/httpd --logfiledir=/var/log/httpd
--activate-module=src/modules/php4/libphp4.a
yann@yoda:~/temp/apache_1.3.22$ make
yann@yoda:~/temp/apache_1.3.22$ su
Password:
root@yoda:/home/yann/temp/apache_1.3.22# make install
make[1]: Leaving directory `/home/yann/temp/apache_1.3.22'
+--------------------------------------------------------+
| You now have successfully built and installed the      |
| Apache 1.3 HTTP server. To verify that Apache actually |
| works correctly you now should first check the         |
| (initially created or preserved) configuration files   |
|                                                        |
|   /etc/httpd/httpd.conf
|                                                        |
| and then you should be able to immediately fire up     |
| Apache the first time by running:                      |
|                                                        |
|   /usr/local/apache/bin/apachectl start
|                                                        |
| Thanks for using Apache.       The Apache Group        |
|                                http://www.apache.org/  |
+--------------------------------------------------------+

Voila, votre serveur apache est compilé et installé, il ne vous reste plus qu'a le configurer. Mais avant il ne faut pas oublier de placer les fichiers de configuration de PHP dans le répertoire de configuration d'Apache. Pour cela on utilise les commande suivantes.
root@yoda:/home/yann/temp/apache_1.3.22# cd ../php-4.0.6
root@yoda:/home/yann/temp/php-4.0.6# cp php.ini-dist /etc/httpd/php.ini

4.2   Configuration du serveur HTTP Apache

Maintenant on peut passer à la phase de configuration d'Apache avant de lancer le serveur web. Pour cela il faut être root et éditer le fichier /etc/httpd/httpd.conf.

La première chose à faire est de vérifier que le serveur écoute le bon port. Pour cela vous devez avoir Port 80, modifiez le fichier si nécessaire.

# Port: The port to which the standalone server listens. For
# ports < 1023, you will need httpd to be run as root initially.
#
#Port 8080
Port 80

Ensuite pour des raisons de sécurité, il est important que le serveur ne s'exécute pas en mode root. Pour cela on va créer un utilisateur web. Au départ le serveur sera lancer par root puis il commutera sur l'utilisateur web. Dans le fichier de configuration on écrira alors les lignes suivantes :
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
#  . On SCO (ODT 3) use "User nouser" and "Group nogroup".
#  . On HPUX you may not be able to use shared memory as nobody, and the
#    suggested workaround is to create a user www and use that user.
#  NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET)
#  when the value of (unsigned)Group is above 60000;
#  don't use Group "#-1" on these systems!
#
#User nobody
#Group "#-1"
User web
Group web

Puis on créera le nouvelle utilisateur et on lui donnera les droits sur les répertoires utilisés.
root@yoda:/usr/local/apache/bin# groupadd web
root@yoda:/usr/local/apache/bin# useradd -g web web
root@yoda:/usr/local/apache/bin# cd /home/httpd
root@yoda:/home/httpd# chown -R web:web *

Ensuite afin que le serveur cherche aussi les fichiers php lorsqu'il entre dans un répertoire, il faut modifier les lignes suivantes :
#
# DirectoryIndex: Name of the file or files to use as a pre-written HTML
# directory index.  Separate multiple entries with spaces.
#
<IfModule mod_dir.c>
    DirectoryIndex index.html index.php
</IfModule>

Il est aussi nécessaire de renseigner Apache sur les fichiers php afin qu'il sache quoi en faire, pour cela il suffit de décommenter les deux lignes suivantes :
    # And for PHP 4.x, use:
    #
    AddType application/x-httpd-php .php
    AddType application/x-httpd-php-source .phps

Pour le reste de la configuration, je vous renvoie à la documentation du serveur Apache. Voila, il ne reste plus qu'a lancer votre serveur Apache en tant que root par la commande suivante :
root@yoda:/usr/local/apache/bin# ./apachectl start
./apachectl start: httpd started
root@yoda:/usr/local/apache/bin#

Un petit ps va vous permettre de vérifier que le serveur est bien exécuter sous l'utilisateur web.
root@yoda:/usr/local/apache/bin# ps aux | grep web
web      15942  0.0  3.9  4796 1852 ?        S    10:22   0:00 /usr/local/apache/bin/httpd
web      15943  0.0  3.9  4796 1852 ?        S    10:22   0:00 /usr/local/apache/bin/httpd
web      15944  0.0  3.9  4796 1852 ?        S    10:22   0:00 /usr/local/apache/bin/httpd
web      15945  0.0  3.9  4796 1852 ?        S    10:22   0:00 /usr/local/apache/bin/httpd
web      15946  0.0  3.9  4796 1852 ?        S    10:22   0:00 /usr/local/apache/bin/httpd
root     15950 18.0  1.1  1324  548 pts/2    S    10:23   0:00 grep web
root@yoda:/usr/local/apache/bin#

Ensuite pour vérifier qu'il fonctionne, lancer votre navigateur préféré, et taper http://localhost. Vous devriez avoir quelque chose du type des figures 1 et 2.

images/lynx.jpg
Figure 1: Capture d'écran de Lynx

ou encore

images/opera.jpg
Figure 2: Capture d'écran d'Opera

Maintenant il ne nous reste plus qu'a tester notre nouveau module PHP. Pour cela créez un fichier test.php dans le répertoire /home/httpd/htdocs (le répertoire par défaut des données du serveur web) qui contient les lignes suivantes :

<html>
<body>
 <?phpinfo()?>
</body>
</html>

Ensuite vous pouvez tester le bon fonctionnement par votre navigateur avec http://localhost/test.php et vous obtenez normalement les figures 3 et 4. Attention, il ne faut pas laisser ce fichier test.php accessible à tous les visiteurs de vote site, en effet ce dernier donne beaucoup d'information concernant votre configuration matériel et logiciel, et quelqu'un de mal intentionné saurait vite utiler ces informations contre vous. Une fois votre test effectué, effacez ce fichier.

images/lynx_php.jpg
Figure 3: Capture d'écran de Lynx

ou encore

images/opera_php.jpg
Figure 4: Capture d'écran d'Opera

Voici un autre petit script qui vous permet de tester le module.

<html>
<body>
<?php
        echo "Hello world\n";
?>
</body>
</html>

Vous pouvez maintenant réaliser un super site web dynamique avec PHP lié à une base de données MySQL. L'utilisation de la base de données fera l'objet d'un autre article.

Enfin si vous voulez stopper le serveur HTTP, il vous suffit de taper la commande suivante en tant que root.

/usr/local/apache/bin/apachectl stop

5  Mise à jour de la version de PHP

5.1  Mise à jour de la version statique

Comme vous avez du le remarquer, PHP evolue très vite, et depuis la rédaction de l'article, au moins deux versions de PHP ont vu le jour (la 4.1.0 et 4.1.1).

Il peut alors être intéressant de mettre à jour, afin de corriger certains bugs.

Pour cela il sera nécessaire de rependre l'installation de PHP décrite au paragraphe 3. Nous partirons de la distribution source. Cette dernière est disponible à l'adresse http://www.php.net. L'installation décrite dans cet article est basée sur la version 4.1.1.

Comme dans la suite du paragraphe, on voit qu'il est aussi nécessaire d'avoir la distribution source du serveur Apache afin de pouvoir lier PHP à ce dernier.

On reprend donc la série de commandes suivantes :

yann@yoda:~/temp$ tar xzf apache_1.3.22.tar.gz
yann@yoda:~/temp$ tar xzf php-4.1.1.tar.gz
yann@yoda:~/temp$ cd apache_1.3.22
yann@yoda:~/temp/apache_1.3.22$ ./configure --sysconfdir=/etc/httpd
--datadir=/home/httpd --logfiledir=/var/log/httpd
yann@yoda:~/temp$ cd php-4.1.1
yann@yoda:~/temp/php-4.1.1$ ./configure --with-mysql
--with-config-file=/etc/httpd --with-apache=../apache_1.3.22
--enable-track-vars
yann@yoda:~/temp/php-4.1.1$ make
yann@yoda:~/temp/php-4.1.1$ su
password :
root@yoda:/home/yann/temp/php-4.1.1# make install

Maintenant PHP 4.1.1 est installé sur votre machine. Mais si vous stoppez et relancez votre serveur Apache et que vous essayez d'afficher le fichier test.php suivant :

<html>
<body>
 <?phpinfo()?>
</body>
</html>

la page affichée fait référence à l'ancien PHP. C'est normal car la serveur apache est encore lié avec cette ancienne version.
C'est normal car PHP fait partie d'apache, car compilé en module statique, et n'a donc pas été mis à jour. Il nous faut donc recompiler le serveur apache à l'aide des instructions suivantes déjà décrites dans le paragraphe 4. Mais avant toute chose, nous allons sauvegarder la configuration de notre serveur (fichier /etc/httpd/httpd.conf), qui serait écrasée par la nouvelle installation
yann@yoda:~/temp/apache_1.3.22$ su
Password:
root@yoda:/home/yann/temp/apache_1.3.22# cp /etc/httpd/httpd.conf /etc/httpd/httpd.conf.sav
root@yoda:/home/yann/temp/apache_1.3.22# exit
yann@yoda:~/temp/apache_1.3.22$ ./configure --sysconfdir=/etc/httpd
--datadir=/home/httpd --logfiledir=/var/log/httpd
--activate-module=src/modules/php4/libphp4.a
yann@yoda:~/temp/apache_1.3.22$ make
yann@yoda:~/temp/apache_1.3.22$ su
Password:
root@yoda:/home/yann/temp/apache_1.3.22# make install
make[1]: Leaving directory `/home/yann/temp/apache_1.3.22'
+--------------------------------------------------------+
| You now have successfully built and installed the      |
| Apache 1.3 HTTP server. To verify that Apache actually |
| works correctly you now should first check the         |
| (initially created or preserved) configuration files   |
|                                                        |
|   /etc/httpd/httpd.conf
|                                                        |
| and then you should be able to immediately fire up     |
| Apache the first time by running:                      |
|                                                        |
|   /usr/local/apache/bin/apachectl start
|                                                        |
| Thanks for using Apache.       The Apache Group        |
|                                http://www.apache.org/  |
+--------------------------------------------------------+

Il reste à restaurer l'ancienne configuration,
yann@yoda:~/temp/apache_1.3.22$ su
Password:
root@yoda:/home/yann/temp/apache_1.3.22# cp /etc/httpd/httpd.conf.sav /etc/httpd/httpd.conf

puis terminer la configuration de PHP
root@yoda:/home/yann/temp/apache_1.3.22# cd ../php-4.1.1
root@yoda:/home/yann/temp/php-4.1.1# cp php.ini-dist /etc/httpd/php.ini

Voila, il ne reste plus qu'a relancer votre serveur Apache en tant que root par la commande suivante :

root@yoda:/usr/local/apache/bin# ./apachectl restart
./apachectl start: httpd restarted
root@yoda:/usr/local/apache/bin#

Maintenant PHP 4.1.1 est réellement installé sur votre machine, et si vous essayez d'afficher le fichier test.php suivant :

<html>
<body>
 <?phpinfo()?>
</body>
</html>

elle fera référence à la nouvelle version de PHP installée. N'oubliez pas d'enlever ce fichier de votre répertoire dédier au web, car il pourrait donner de nombreuses informations à un pirate éventuel.

5.2  Mise à jour de la version dynamique

Comme PHP a été configuré comme un module d'apache, ici nous n'aurons pas à recompiler Apache.
Pour cela il sera nécessaire de rependre l'installation de PHP décrite au paragraphe 3. Nous partirons de la distribution source. Cette dernière est disponible à l'adresse http://www.php.net. L'installation décrite dans cet article est basée sur la version 4.1.1.

On reprend donc la série de commandes suivantes :

yann@yoda:~/temp$ cd php-4.1.1
yann@yoda:~/temp/php-4.1.1$ ./configure --with-mysql --with-apxs
--with-config-file=/etc/httpd --with-apache=../apache_1.3.22

nusSi le programme configure vous retourne une erreur car il ne trouve pas apxs, vous pouvez recommencer en lui indiquant le chemin complet vers apxs, pour votre configuration :
yann@yoda:~/temp/php-4.1.1$ ./configure --with-mysql
--with-apxs=/usr/local/apache/bin/apxs
--with-config-file=/etc/httpd --with-apache=../apache_1.3.22

Ici comme nous voulons interfacer PHP avec une Base de doonnées MySQL,nous ajoutons -with-mysql. -enable-track-vars permet aux variables GPC-GET et POST et autres cookies d'être envoyés au serveur et d'être pistés.

Il ne nous reste plus qu'a compiler PHP et l'installer par les commandes suivantes :

yann@yoda:~/temp/php-4.1.1$ make
yann@yoda:~/temp/php-4.1.1$ su
password :
root@yoda:/home/yann/temp/php-4.0.6# make install

Maintenant PHP 4.1.1 est installé sur votre machine. Mais si vous stoppez et relancez votre serveur Apache et que vous essayez d'afficher le fichier test.php suivant :

<html>
<body>
 <?phpinfo()?>
</body>
</html>

la page html affichée fera référence à la nouvelle version de PHP installée.

6  Jouons avec les bases de données

Cette section de l'article est en partie reprise de la revue Linux France Mag (Hors Série N°9 Décembre/Janvier 2001) et de mes tests personnels. On va commencer par se connecter à la base de données MySQL. Pour cela il faut bien sur que le démon de la base fonctionne. Pour cela la simple commande
mysql@Qui-GonJinn:/usr/local/mysql/bin >  ps aux | grep mysqld
mysql     1485  0.0  0.3  2052  972 pts/0    S    11:45   0:00
sh /usr/local/mysql/bin/safe_mysqld --datadir=/usr/local/mysql/var
--pid-file=/usr/local/mysql/var/Qui-GonJinn.pid
mysql     1497  0.0  0.8 12308 2252 pts/0    SN   11:45   0:00
/usr/local/mysql/libexec/mysqld --basedir=/usr/local/mysql
--datadir=/usr/local/mysql/var --pid-file=/usr/local/mysql/var/Qui-GonJinn.pid --skip-locking
mysql     1499  0.0  0.8 12308 2252 pts/0    SN   11:45   0:00
/usr/local/mysql/libexec/mysqld --basedir=/usr/local/mysql
--datadir=/usr/local/mysql/var --pid-file=/usr/local/mysql/var/Qui-GonJinn.pid --skip-locking
mysql     1500  0.0  0.8 12308 2252 pts/0    SN   11:45   0:00
/usr/local/mysql/libexec/mysqld --basedir=/usr/local/mysql
--datadir=/usr/local/mysql/var --pid-file=/usr/local/mysql/var/Qui-GonJinn.pid --skip-locking
mysql     1530  0.0  0.1  1316  512 pts/0    S    11:53   0:00 grep mysqld
mysql@Qui-GonJinn:/usr/local/mysql/bin >

Sinon les commandes suivantes permettent de la mettre en route.
mysql@Qui-GonJinn:/home/yann/temp > /usr/local/mysql/bin/mysql.server start
mysql@Qui-GonJinn:/home/yann/temp > Starting mysqld daemon with databases from
/usr/local/mysql/var

ou encore
mysql@Qui-GonJinn:/home/yann/temp > /usr/local/mysql/bin/safemysql&
mysql@Qui-GonJinn:/home/yann/temp > Starting mysqld daemon with databases from
/usr/local/mysql/var

C'est bon elle fonctionne. Il ne reste plus qu'a se connecter.
mysql@Qui-GonJinn:/usr/local/mysql/bin > ./mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10 to server version: 3.23.46

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

On va donc créer une nouvelle base de données test_base. Je sais le nom n'est pas très malin, mais il représente bien ce que l'on veut faire : un test :-).
mysql> create database test_base;
Query OK, 1 row affected (0.00 sec)

mysql>

Note : A chaque fois, c'est pareil, j'oublie le ; à la fin de la commande SQL. Essayer donc d'être plus attentif que moi, sinon vous obtenez un truc du genre :
mysql> create database test_base
    -> ;
Query OK, 1 row affected (0.00 sec)

mysql>

La base est crée avec l'utilisateur root de MySQL (ici l'utilisateur mysql), et il n'est pas conseillé que cette l'utilisateur fasse des manipulations autres que l'administration de MySQL. En d'autres termes, il ne doit s'occupper que de la base de données mysql qui gère toutes les bases. On va donc donner tous les privilèges à un autre utilisateur qui aura en charge cette nouvelle base de données.
Comme cette dernière est créée en vue de fournir des informations pour des pages web, via PHP, l'utilisateur choisi sera web, l'aministrateur des pages web et du serveur HTTP.
On va tout d'abord se connecter sur la nouvelle base par la commande suivante :
mysql> use test_base;
Database changed

mysql>

Ensuite on accorde les privilèges sur toutes les tables de la base test_base à l'utilisateur web par la commande suivante :
mysql> GRANT ALL PRIVILEGES ON test_base.* to web@localhost;
Query OK, 0 rows affected (0.04 sec)

mysql>

ou encore
mysql>  GRANT ALL PRIVILEGES ON test_base.* TO web@'Qui-GonJinn';
Query OK, 0 rows affected (0.00 sec)

mysql>

On va maintenant quitter mysql et donner un mot de passe au nouvel utilisateur de la base, web.
mysql@Qui-GonJinn:/usr/local/mysql/bin > ./mysqladmin -p -uweb password 'motdepasse'
Enter password:
mysql@Qui-GonJinn:/usr/local/mysql/bin >

Attention : comme l'utilisateur web vient d'être créer au niveau de la base il n'a pas encore de mot de passe, donc à l'invite password:, tapez juste return. Voilà, il ne nous reste plus qu'à devenir l'utilisateur web, et à se connecter à la base test_base.
yann@Qui-GonJinn:~ > su web
Password:
web@Qui-GonJinn:/home/yann > cd
web@Qui-GonJinn:~ > /usr/local/mysql/bin/mysql -p -uweb test_base
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11 to server version: 3.23.46

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

Nous allons créer notre première table, dans cette nouvelle base de données. Cette base de donnée doit nous permettre de gérer les diverses publications des chercheurs d'un laboratoire. Pour cela nous aurons besoin de plusieurs tables différentes qui seront reliées entre elle. Je ne vais pas ici vous faire un cours de base de données. Mais nous utiliserons une représentation relationnelle des données afin de simplifier le mise en uvre sous MySQL. Je vous renvoie à d'autres ouvrages en ce qui concerne la modélisation.
D'une manière simple on peut dire que l'on va stocker les données issues de différents objets dans des tableaux, qui comprendront plusieurs colonnes (les différentes caractéristiques d'un objet matériel ou non). Par exemple, l'objet "personne" comporte plusieurs caractéristiques comme son nom, ses prénoms, sa date de naissance, sa taille, son sexe, etc... Mais l'objet "personne" serait bien seul dans l'univers s'il n'entrait pas en relation avec d'autres objets de la même classe que lui (lors d'un mariage), ou d'autres classe d'objets (comme lors de l'action de l'achat d'une voiture) qui possèdent leurs caractéristiques propres. Ces différentes classes d'objets seront modélisées par des tables, dont les lignes représentes des instances, et les colonnes les caractéristiques propres de l'objet. Il est à noter que chaque objet de la classe (c'est à dire une ligne de la table) ne doit désigné qu'un seul et unique objet.
Dans cette exemple d'une personne qui achète une voiture, on voit bien qu'une relation concerne les deux acteurs "la personne" et la "voiture". D'un coté, la personne achète la voiture, et de l'autre la voiture est achetée par la personne.Bien sur on pourrait tout stocker dans une seule table (les personnes et les voitures achetées), mais il y aurait redondance de données dès qu'une personne achète plus d'une voiture, et dès qu'il existe plusieurs exemplaires d'une même voiture.

Pour cela nous allons créer une nouvelle table qui va modéliser la relation. Celle-ci va mettre en concordance une personne avec la ou les voiture achetée sans répéter toutes les caractéristiques des objets. Afin d'avoir un table relation de taille réduite, il est nécessaire de pouvoir représenter un objet particulier d'une classe par un minimum de caractéristiques. Cela est possible grâce à la notion de clé.

Cette clé sera un ensemble minimum de caractéristiques de l'objet qui permet de l'identifier de manière unique. Le plus souvent elle est choisie comme un compteur que l'on incrémente à chaque nouvel objet de la classe, ce qui l'identifie de manière unique. Si nous considérons qu'une personne sera identifiée de manière unique par son numéro de sécurité sociale, et qu'une voiture le sera par sont numéro de série, la table relation mettre en concordance, des numéros de sécurité social et des numéros de série de voiture.

Ce concept sera généralisé à toutes les relations que nous aurons dans notre base. Bien sur, ce n'est pas aussi simple que cela, mais, le principe est de stocker toutes les informations et les liens entre ces informations en essayant de minimiser l'espace de stockage.

Vous venez donc, en une quinzaine de lignes, d'avoir votre premier cours de SGBD, cool non!!!

Notre base aura l'architecture suivante :

images/bdd_test.png
Figure 5: Modèle conceptuel de la base de données

Ceci conduit à la définition du modèle relationnelle suivante :

Nous allons maintenant créer les différentes tables et les remplir.
mysql> CREATE TABLE `specialites` (
    -> `id_specia` INT(10) UNSIGNED DEFAULT '0' NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> `abbrev` VARCHAR(10) NOT NULL,
    -> `lib_fr` VARCHAR(25) DEFAULT NULL,
    -> `lib_an` VARCHAR(25) DEFAULT NULL
    -> )
    -> COMMENT = 'Tables des spécialités des auteurs de publications';
Query OK, 0 rows affected (0.00 sec)

mysql> show fields from specialites;
+-----------+------------------+------+-----+---------+----------------+
| Field     | Type             | Null | Key | Default | Extra          |
+-----------+------------------+------+-----+---------+----------------+
| id_specia | int(10) unsigned |      | PRI | NULL    | auto_increment |
| abbrev    | varchar(10)      |      |     |         |                |
| lib_fr    | varchar(25)      | YES  |     | NULL    |                |
| lib_an    | varchar(25)      | YES  |     | NULL    |                |
+-----------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql>

Malheureusement, nous avons fait une erreur dans la définition de la table. Nous allons la modifier :
mysql> ALTER TABLE `test_base`.`specialites` CHANGE `abbrev` `abbrev` VARCHAR(10),
    -> CHANGE `lib_fr` `lib_fr` VARCHAR(25) NOT NULL, CHANGE `lib_an` `lib_an`
        -> VARCHAR(25) NOT NULL;

mysql> show fields from specialites;
+-----------+------------------+------+-----+---------+----------------+
| Field     | Type             | Null | Key | Default | Extra          |
+-----------+------------------+------+-----+---------+----------------+
| id_specia | int(10) unsigned |      | PRI | NULL    | auto_increment |
| abbrev    | varchar(10)      | YES  |     | NULL    |                |
| lib_fr    | varchar(25)      |      |     |         |                |
| lib_an    | varchar(25)      |      |     |         |                |
+-----------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql>

On y insère à présent quelques données afin de pouvoir réaliser des requêtes un peu plus tard.
mysql> INSERT INTO `specialites` (`id_specia`,`abbrev`,`lib_fr`,`lib_an`)
VALUES ('', 'INFO','Informatique','Informatic');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `specialites` (`id_specia`,`abbrev`,`lib_fr`,`lib_an`)
VALUES ('', 'MECA','Mécanique','Mecanic');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `specialites` (`id_specia`,`abbrev`,`lib_fr`,`lib_an`)
VALUES ('', 'AUTO','Automatique','Automatic');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `specialites` (`id_specia`,`abbrev`,`lib_fr`,`lib_an`)
VALUES ('', 'PSYCHO','Psychologie','Psychology');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `specialites` (`id_specia`,`abbrev`,`lib_fr`,`lib_an`)
VALUES ('', 'ERGO','Ergonomie','Ergonomic');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `specialites` (`id_specia`,`abbrev`,`lib_fr`,`lib_an`)
VALUES ('', 'GEN','Général','General');
Query OK, 1 row affected (0.00 sec)

mysql>

et voici le résultat à l'aide d'une première requête :
mysql> select * from specialites;
+-----------+--------+--------------+------------+
| id_specia | abbrev | lib_fr       | lib_an     |
+-----------+--------+--------------+------------+
|         1 | INFO   | Informatique | Informatic |
|         2 | MECA   | Mécanique    | Mecanic    |
|         3 | AUTO   | Automatique  | Automatic  |
|         4 | PSYCHO | Psychologie  | Psychology |
|         5 | ERGO   | Ergonomie    | Ergonomic  |
|         6 | GEN    | Général      | General    |
+-----------+--------+--------------+------------+
6 rows in set (0.00 sec)

mysql>

Et voici la table qui va permettre de donner un status à chaque personne :
mysql> CREATE TABLE `status` (
    -> `id_status` INT(10) UNSIGNED DEFAULT '0' NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> `abbrev` VARCHAR(10) DEFAULT NULL,
    -> `sta_fr` VARCHAR(25) NOT NULL,
    -> `sta_an` VARCHAR(25) NOT NULL,
    -> `ordre` INT(10) UNSIGNED DEFAULT NULL
    -> )
    -> COMMENT = 'Tables des statuts des auteurs de publications';
Query OK, 0 rows affected (0.00 sec)

mysql> show tables;
+---------------------+
| Tables_in_test_base |
+---------------------+
| auteurs             |
| specialites         |
| status              |
+---------------------+
3 rows in set (0.00 sec)

mysql>

On remplit donc cette nouvelle table avec tous les status connus :
mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'PR','Professeur','Professor','1');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'MCF','Maître de conférences','Assistant Professor','20');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'DR','Directeur de recherche','Research Director','5');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'CR','Chargé de recherche','Researcher','15');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'TH','Doctorant','Doctoral Student','55');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'ETU','Etudiant','Student','65');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'DEA','Etudiant en DEA','Student','60');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'IR','Ingénieur de recherche','Research Engineer','45');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'ASS','Assistant','Assistant','25');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'Autre','Autre','Other','80');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'MON','Moniteur','Monitor','52');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'PAST','PAST','Assistant Professor','40');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'ATER','ATER','Doctoral Student','30');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'SEC','Secrétaire','Secretary','70');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'DOC','Docteur','Doctor','35');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'MC-HDR','Maître de conférences HDR','Assistant Professor HDR','10');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'PRAG','PRAG','Assistant Professor','23');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `status` (`id_status`,`abbrev`, `sta_fr`, `sta_an`, `ordre`)
VALUES ('', 'AI','Assistant ingénieur','Assistant Engineer','51');
Query OK, 1 row affected (0.00 sec)

mysql> select * from status;
+-----------+--------+---------------------------+-------------------------+-------+
| id_status | abbrev | sta_fr                    | sta_an                  | ordre |
+-----------+--------+---------------------------+-------------------------+-------+
|         1 | PR     | Professeur                | Professor               |     1 |
|         2 | MCF    | Maître de conférences     | Assistant Professor     |    20 |
|         3 | DR     | Directeur de recherche    | Research Director       |     5 |
|         4 | CR     | Chargé de recherche       | Researcher              |    15 |
|         5 | TH     | Doctorant                 | Doctoral Student        |    55 |
|         6 | ETU    | Etudiant                  | Student                 |    65 |
|         7 | DEA    | Etudiant en DEA           | Student                 |    60 |
|         8 | IR     | Ingénieur de recherche    | Research Engineer       |    45 |
|         9 | ASS    | Assistant                 | Assistant               |    25 |
|        10 | Autre  | Autre                     | Other                   |    80 |
|        11 | MON    | Moniteur                  | Monitor                 |    52 |
|        12 | PAST   | PAST                      | Assistant Professor     |    40 |
|        13 | ATER   | ATER                      | Doctoral Student        |    30 |
|        14 | SEC    | Secrétaire                | Secretary               |    70 |
|        15 | DOC    | Docteur                   | Doctor                  |    35 |
|        16 | MC-HDR | Maître de conférences HDR | Assistant Professor HDR |    10 |
|        17 | PRAG   | PRAG                      | Assistant Professor     |    23 |
|        18 | AI     | Assistant ingénieur       | Assistant Engineer      |    51 |
+-----------+--------+---------------------------+-------------------------+-------+
18 rows in set (0.00 sec)

mysql>

Voici une table un peu plus conséquente, qui va permettre de stocker les coordonnées de tous les auteurs de communications :
mysql> CREATE TABLE `auteurs` (
    -> `id_auteur` INT(10) UNSIGNED DEFAULT '0' NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> `nom` VARCHAR(30) NOT NULL,
    -> `prenom` VARCHAR(20) NOT NULL,
    -> `id_status` INT(10) UNSIGNED DEFAULT NULL,
    -> `id_specia` INT(10) UNSIGNED DEFAULT NULL,
    -> `e_mail` VARCHAR(50) DEFAULT NULL,
    -> `rep_pages_perso` VARCHAR(100) DEFAULT NULL,
    -> `origine` VARCHAR(50) DEFAULT 'Inconnu',
    -> `num_telephone` VARCHAR(30) DEFAULT NULL,
    -> `num_poste` VARCHAR(20) DEFAULT NULL,
    -> `bureau` VARCHAR(10) DEFAULT NULL,
    -> `batiment` VARCHAR(20) DEFAULT NULL
    -> )
    -> COMMENT = 'Tables des auteurs de publications';
Query OK, 0 rows affected (0.00 sec)

mysql>

On peut voir que les tables ont été créées, et lister leurs champs
mysql> show tables;
+---------------------+
| Tables_in_test_base |
+---------------------+
| auteurs             |
| specialites         |
| status              |
+---------------------+
3 rows in set (0.00 sec)

mysql> show fields from auteurs;
+-----------------+------------------+------+-----+---------+----------------+
| Field           | Type             | Null | Key | Default | Extra          |
+-----------------+------------------+------+-----+---------+----------------+
| id_auteur       | int(10) unsigned |      | PRI | NULL    | auto_increment |
| nom             | varchar(30)      |      |     |         |                |
| prenom          | varchar(20)      |      |     |         |                |
| id_status       | int(10) unsigned | YES  |     | NULL    |                |
| id_specia       | int(10) unsigned | YES  |     | NULL    |                |
| e_mail          | varchar(50)      | YES  |     | NULL    |                |
| rep_pages_perso | varchar(100)     | YES  |     | NULL    |                |
| origine         | varchar(50)      | YES  |     | Inconnu |                |
| num_telephone   | varchar(30)      | YES  |     | NULL    |                |
| num_poste       | varchar(20)      | YES  |     | NULL    |                |
| bureau          | varchar(10)      | YES  |     | NULL    |                |
| batiment        | varchar(20)      | YES  |     | NULL    |                |
+-----------------+------------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)

mysql>

On peut ensuite y insérer quelques données :
mysql> INSERT INTO auteurs VALUES (1, 'MORERE', 'Yann', 2, 3, 'morere@imaginaire.org',
 'http://ymorere.multimania.com', 'Inconnu', '555 555 554', '55 54', '4', 'Imag2');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO auteurs VALUES (2, 'DURANT', 'Alain', 1, 3, 'durant@imaginaire.org',
 NULL, 'Inconnu', '555 555 556', '55 56', '1', 'Imag2');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO auteurs VALUES (3, 'DUPONT', 'Guy', 16, 3, 'dupont@imaginaire.org',
 NULL, 'Inconnu', '555 555 555', '55 55', '2', 'Imag2');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO auteurs VALUES (4, 'DUSCHMOLL', 'Olivier', 2, 3,
 'duschmoll@imaginaire.org', NULL, 'Inconnu', '555 555 553', '55 53', '9', 'Imag2');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO auteurs VALUES (5, 'DUMOULIN', 'Stéphane', 2, 1,
 'dumoulin@imaginaire.org', 'http://www.imaginaire.org/~dumoulin', 'Inconnu', '555 555 552',
  '55 52', '8', 'Imag2');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO auteurs VALUES (6, 'DUPIERRE', 'Odile', 2, 3, 'dupierrre@imaginaire@org',
 NULL, 'Inconnu', '555 555 557', '55 57', '6', 'Imag2');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO auteurs VALUES (7, 'DUTILLEUL', 'Abdallah', 2, 3,
 'dutilleul@imaginaire.org', NULL, 'Inconnu', '555 555 559', '55 59', '12', 'Imag2');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO auteurs VALUES (8, 'DUSAPIN', 'Pierre', 2, 3, 'dusapin@imaginaire.org',
 NULL, 'Inconnu', '555 555 560', '55 60', '11', 'Imag2');
Query OK, 1 row affected (0.01 sec)

mysql>

Et voici quelques premières jolies requêtes :
mysql> select nom, prenom from auteurs;
+-----------+----------+
| nom       | prenom   |
+-----------+----------+
| MORERE    | Yann     |
| DURANT    | Alain    |
| DUPONT    | Guy      |
| DUSCHMOLL | Olivier  |
| DUMOULIN  | Stéphane |
| DUPIERRE  | Odile    |
| DUTILLEUL | Abdallah |
| DUSAPIN   | Pierre   |
+-----------+----------+
8 rows in set (0.00 sec)

mysql> select nom, prenom from auteurs,status
    -> WHERE auteurs.id_status=status.id_status and abbrev='PR';
+--------+--------+
| nom    | prenom |
+--------+--------+
| DURANT | Alain  |
+--------+--------+
1 row in set (0.00 sec)

mysql>

Création de la table documentation

mysql> CREATE TABLE docs (
    -> id_docs int(10) unsigned NOT NULL auto_increment,
    -> titre varchar(255) NOT NULL default '',
    -> annee int(10) NOT NULL default '0',
    -> type varchar(20) NOT NULL default '',
    -> langue varchar(20) NOT NULL default '',
    -> fichier varchar(255) NOT NULL default '',
    -> acces tinyint(1) NOT NULL default '0',
    -> PRIMARY KEY  (id_docs)
    -> ) TYPE=MyISAM COMMENT='Tables des publications du laboratoire';
        Query OK, 0 rows affected (0.00 sec)

mysql>

Puis on la rempli avec quelques données
mysql> INSERT INTO docs VALUES (1, 'Mise en place d\'un serveur WEB', 2002, 'article', 'française', '', 0);
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO docs VALUES (2, 'La culture du blé sous marin', 2012, 'article', 'française', '', 0);
Query OK, 1 row affected (0.01 sec)

mysql>

Maintenant créons la table qui fera la relation entre les auteurs et les documentation. Il s'agit de la table
mysql> CREATE TABLE lien_docs_auteurs (
    -> id_docs int(10) unsigned NOT NULL default '0',
    -> id_auteur int(10) unsigned NOT NULL default '0',
    -> ordre tinyint(3) unsigned NOT NULL default '0',
    -> PRIMARY KEY  (id_docs,id_auteur,ordre)
    -> ) TYPE=MyISAM COMMENT='Table de lien entre les auteurs et les documents'; #
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO lien_docs_auteurs VALUES (1, 1, 2);
Query OK, 1 row affected (0.01 sec)

mysql>INSERT INTO lien_docs_auteurs VALUES (1, 2, 1);
Query OK, 1 row affected (0.01 sec)

mysql>INSERT INTO lien_docs_auteurs VALUES (2, 5, 1);
Query OK, 1 row affected (0.01 sec)

mysql>INSERT INTO lien_docs_auteurs VALUES (2, 6, 3);
Query OK, 1 row affected (0.01 sec)

mysql>INSERT INTO lien_docs_auteurs VALUES (2, 7, 1);
Query OK, 1 row affected (0.01 sec)

mysql>

Maintenant les publications sont liées avec les auteurs, et il est possible de faire des requêtes plus intéressantes. Si une relations n'est pas satisfaisante, en ce sens qu'elle implique des répétitions au niveau de sa population et qu'elle pose des problèmes lors des insertions/modifications/suppressions de tuples, trouver un ensemble de relations satisfaisantes et qui décrive les mêmes informations. La méthode consiste à décomposer la relation en deux (ou plusieurs) relations. Pour cela, il est nécessaire de disposer de deux opérations qui permettent, l'une, de découper une relation en sousrelations (la projection), et l'autre, de recomposer la relation à partir de ses sous-relations (la jointure).

Par exemple si l'on veut retrouver la liste des auteurs qui ont écrits les articles, il est nécessaire de recomposer à l'aide des trois relations (tables) auteurs, docs,lien_docs_auteurs comme décrit ci-dessous.

mysql> select nom,titre from auteurs, docs,lien_docs_auteurs
    ->  where (auteurs.id_auteur=lien_docs_auteurs.id_auteur) and
         (lien_docs_auteurs.id_docs=docs.id_docs) order by docs.id_docs, ordre;
+-----------+--------------------------------+
| nom       | titre                          |
+-----------+--------------------------------+
| DURANT    | Mise en place d'un serveur WEB |
| MORERE    | Mise en place d'un serveur WEB |
| DUTILLEUL | La culture du blé sous marin   |
| DUMOULIN  | La culture du blé sous marin   |
| DUPIERRE  | La culture du blé sous marin   |
+-----------+--------------------------------+
5 rows in set (0.00 sec)

mysql>

En ce qui concerne les autres clauses (commandes MySQL) je vous laisse découvrir cela à l'aide de la documentation de MySQL (fichier docMySQL3.23_v4.ps). On retrouvera entre autre les clauses suivantes :

SQL offre les fonctions d'agrégation usuelles: qui opèrent sur un ensemble de valeurs prises par un attribut, ou pour COUNT uniquement, sur un ensemble de tuples. Exemple : quel est le nombre de livraisons faites par le fournisseur 1 ?
SELECT COUNT (*) /* on compte les tuples de PUF tels
FROM PUF que NF = 1 */
WHERE NF=1

Exemple : combien de produits différents a livré le fournisseur 1 ? Attention : il faut ôter les doubles, car COUNT compte toutes les valeurs, y compris les valeurs doubles.
SELECT COUNT (DISTINCT NP)
FROM PUF
WHERE NF=1

SQL offre une Recherche avec partition des tuples d'une relation : GROUP BY
Exemple : combien de produits différents ont été livrés par chacun des fournisseurs ? Il faut partitionner l'ensemble des tuples de PUF en un sous-ensemble (ou groupe) par numéro de fournisseur. C'est ce que permet la clause GROUP BY.
SELECT NF, COUNT (DISTINCT NP)
FROM PUF
GROUP BY NF

Cette instruction génère dans le SGBD les actions suivantes :

  1. Classer les tuples de PUF, groupe par groupe (un groupe = ensemble des tuples ayant même NF),
  2. Pour chaque groupe : évaluer le résultat du SELECT (compter le nombre de NP différents dans ce groupe).
Exemple : combien de produits différents ont été livrés par chacun des fournisseurs, tels que la quantité totale de produits livrés par ce fournisseur soit supérieure à l000 ?
SELECT NF, COUNT (DISTINCT NP)
FROM PUF
GROUP BY NF
HAVING SUM (qt) > 1000

La clause "HAVING <condition>" permet de sélectionner les groupes qui satisfont une condition. Attention, contrairement à la clause "WHERE <condition>", la condition ne porte pas sur un tuple mais sur l'ensemble des tuples d'un groupe.

Voici pour cette petite initiation à MySQL. Dans le point suivant nous allons voir que l'on utiliser une interface plus conviviale pour gérer notre base de donnée que la console et les lignes de codes SQL. Il s'agit de phpMyAdmin.

7  Installation de phpMyAdmin

phpMyAdmin est ensemble de scripts PHP qui permet d'administrer une base de données MySQL par l'intermédiaire d'un navigateur WEB, et donc, à distance, à travers Internet. Vous pourrez trouver les nouvelles version de phpMyAdmin à l'adresse suivante http://phpmyadmin.sourceforge.net/ ou http://phpwizard.net/projects/phpMyAdmin/ aux formats suivants : .zip, .tar.gz and .tar.bz2.
phpMyAdmin peut gérer un server MySQL complet (il faut alors être super utilisateur root) mais aussi une simple base de données. Pour cela il est nécessaire de configurer convenablement un utilisateur MySQL qui puisse lire et ecrire sur la base de données désirées.
phpMyAdmin est prévu pour réaliser les actions suivantes :

7.1  Installation

Cette partie est simplement une traduction d'une partie du fichier Documentation.txt livré avec la distribution de phpMyAdmin.
NOTE : phpMyAdmin n'applique aucune méthode particulière en ce qui concerne les méthodes de sécurités pour le serveur de base de données MySQL. Ce travail est réservé à l'administrateur qui alloue les permissions sur les bases de données d'une manière adéquate.

7.1.1  Installation Rapide

  1. Détarer ou Unzipper la distribution par la commande suivante : tar xzvf phpMyAdmin_x.x.x.tar.gz dans le répertoire root de votre serveur HTTP. Dans la cas de Apache, il s'agit le plus souvent de /home/httpd/htdocs si vous n'avez pas modifier la configuration par défaut de /etc/httpd.conf
  2. Ouvrir le fichier config.inc.php dans votre éditeur favoris et changer les valeur de host, user, password et le mode d'authentification afin de le configurer pour votre machine. Insérer aussi la valeur correct (i.e. l'adresse) pour la variable $cfgPmaAbsoluteUri. Il s'agit en fait du chemin complet du répertoire de ou est installé phpMyAdmin. Jeter un oeil dans la section configuration pour une explication des toutes ces valeurs.
  3. Il est recommandé de protégé le répertoire dans lequel vous avez installé phpMyAdmin (même si vous êtes dans un Intranet, ou que vous utilisiez l'authentification par cookie), par exemple avec HTTP-AUT (à l'aide d'un fichier .htaccess). Rendez-vous dans la section configuration pour plus de détails.
  4. Ouvrir ensuite dans votre navigateur préféré le fichier http://<www.your-host.com>/<your-install-dir>/index.php. phpMyAdmin vous affiche maintenant (après authentification si vous l'avez activée) un écran d'accueil et vos bases de données.

7.1.2   Mettre à jour à partir d'un version plus ancienne

Avec l'utilisation des modes d'authentification Mode d'authentification "http" : Mode d'authentification "cookie" : Mode d'authentification "config" :

Pour plus d'information sur le mise en uvre de ces méthodes, je vous remvoie au paragraphe suivant. aire un rep séparer pour l'admin root de MySQL pour phpMyAdmin et l'utilisateur de la base.

8  Sécurisation de votre installation Web

Cette partie est tirée d'un article de JML dit Jean-Marc LICHTLE, email jean-marc.lichtle@gadz.org, ingénieur Arts et Métiers promo CH173

8.1  Sécurisation d'Apache

8.1.1  Protection par .htaccess

Le principe consiste à créer dans le sous répertoire à protéger un fichier nommé .htaccess (commençant par un point donc caché) et qui va en limiter les droits d'accès. En fait .htaccess va renvoyer vers un fichier contenant les logins et mots de passe des utilisateurs autorisés. Ce fichier de mots de passe peut porter un nom quelconque. Habituellement ce dernier est rangé dans /etc/httpd/auth/, répertoire qu'il convient éventuellement de créer puisqu'il n'existe pas après l'installation de base. Il est assez logique que tous les fichiers d'authentification seront rangés dans le même sous-répertoire. Il est de ce fait judicieux de choisir des noms de fichiers qui soient parlant et qui rappellent l'objet de la protection, par exemple test.users pour le fichier qui définira les droits d'accès des diféfrents utilisateurs au sous répertoire test. L'emploi de /etc/httpd/auth/ pour ranger les fichiers d'autorisation est une pure question de convention. Ces fichiers pourraient aussi bien être rangés n'importe ou ailleurs. Il va toutefois sans dire (mais mieux en le disant) que ces fichiers doivent être hors de portée des visiteurs, en clair ne doivent pas faire partie de l'arborescence /var/www/html/...

Création de .htaccess   Exemple simple : Avec un éditeur quelconque créer le fichier minimum suivant :

AuthUserFile /etc/httpd/auth/test.users 
AuthName "Accès restreint"
AuthType Basic 
Require valid-user 

ou encore
AuthUserFile /etc/httpd/auth/test.users 
AuthName "Accès restreint"
AuthType Basic 
Require user lambda 

pour n'autoriser que l'utilisateur lambda.
Sauvegardez... AuthUserFile définit quel est le fichier chargé de contenir les autorisations. La première partie de l'adresse AuthUserFile peut donc être omise éventuellement. AuthName précise le message qui sera affiché dans la boite de dialogue, dans ce cas Äccès restreint à localhost" si la machine est nommée localhost. Nous verrons plus loin l'intérêt de choisir un message aussi explicite que possible.

Création du fichier des autorisations d'accès   La première étape consiste à créer, s'il n'existe pas encore, le sous répertoire /etc/httpd/auth/ qui contiendra les autorisations. Le fichier d'autorisation lui-même se crée (et s'entretient) avec la commande htpasswd.
Attention : la commande htpasswd peut être lancée aussi bien par un utilisateur de base que par l'administrateur. Toutefois, les fichiers contenus dans /etc étant tous la propriété de root je préconise, dans un but de cohérence, de lancer cette commande uniquement sous compte root. De toute façon, sauf à imaginer que /etc/httpd/auth/ soit propriété d'un utilisateur non root, le lancement de htpasswd depuis un login non root conduirait à un échec à l'enregistrement des données.
Syntaxes :

La consultation de .htaccess se fait à chaque accès du serveur Apache au sous-répertoire concerné. Avantage : la nouvelle configuration entre en action immédiatement sans qu'il soit nécessaire de relancer le serveur Apache pour recharger la nouvelle configuration.

8.1.2  Protection par modification de httpd.conf

Le principe est assez similaire à ce qui a été exposé ci-dessus si ce n'est que le renvoi vers le fichier des autorisations est réalisé dans /etc/httpd/conf/httpd.conf. Pour mettre en place ce renvoi éditez ce fichier et ajoutez (par exemple tout à la fin) les lignes suivantes :
<Directory /var/www/html/test> 
AuthName "Accès limité" 
AuthUserFile /etc/httpd/auth/test.users 
AuthType Basic require valid-user 
</Directory>

Pour protéger plusieurs répertoires créez plusieurs paragraphes <Directory> </Directory>. Sauvegardez puis relancez le démon Apache (comme root : /etc/rc.d/init.d/httpd restart). En effet dans ce cas vous venez de modifier un des fichiers de configuration du serveur, fichier qui est lu au moment du chargement de Apache. Il convient donc de forcer Apache à relire ce fichier pour prendre en compte les modifications.

8.1.3  Différence entre les deux méthodes .htaccess et httpd.conf

Votre attention aura certainement été attirée par le similitude de rédaction entre les deux solutions. Cette similitude n'est absolument pas fortuite et provient simplement de la logique interne du fonctionnement d'Apache. Le serveur lit au lancement les paramètres de configuration stockés dans httpd.conf. Il ne les relira ensuite qu'en cas de demande explicite (restart).
Par contre, il cherchera à chaque requête d'un navigateur, à lire un éventuel fichier .htaccess contenu dans le sous-répertoire concerné par la demande. S'il le trouve les informations contenues dans ce fichier remplaceront, pour la durée de la requête, celles qui sont contenues dans httpd.conf. En clair vous pouvez "masquer" la configuration officielle contenue dans httpd.conf en proposant une nouvelle configuration dans un .htaccess. Faites l'essai en mettant en place une protection double : Vous pourrez vérifier simplement (en renommant .htaccess par exemple) que la protection par .htaccess, lorsqu'elle est en place, remplace bien la protection induite par httpd.conf.

L'intérêt de cette petite démonstration ne semble pas évident. Trois éléments méritent toutefois d'être retenus :

  1. Une protection par .htaccess nécessite un travail supplémentaire d'analyse de la part du serveur (à prendre en compte pour les serveurs très chargés ou installés sur des machines poussives).
  2. Certaines directives de httpd.conf peuvent être neutralisées, modifiées...
  3. Une protection par .htaccess est prise en compte immédiatement sans nécessité d'intervenir sur le serveur.

8.1.4  Protection de fichiers particuliers dans un sous répertoire

La protection par .htaccess décrite ci-dessus s'applique à l'ensemble d'un sous-répertoire. En fait vous pouvez différencier, si vous le souhaitez, les accès aux fichiers. La syntaxe de .htaccess s'en trouve légèrement modifiée, par exemple pour protéger un fichier nommé common.php :
<Files common.php> 
AuthName "Accès limité au fichier common.php par .htaccess" 
AuthUserFile /etc/httpd/auth/common.users 
AuthType Basic require valid-user 
</Files>

L'intérêt de libeller AuthName de façon explicite apparaît ici de façon nette. Lors des essais vous pourrez en effet savoir immédiatement quels sont les contrôles d'accès qui sont en place.
Vous pouvez souhaiter protéger plus spécifiquement l'accès à un fichier particulier. La solution consiste à créer un fichier .htaccess libellé comme suit : Exemple pour protéger un fichier common.php :
<Files common.php> 
Order Deny,Allow Deny from All 
</Files>

Pour protéger plusieurs fichiers il suffit de créer plusieurs rubriques <Files> </Files>.
Attention : cette méthode interdit l'accès via le serveur Web pour tout le monde, y compris le propriétaire du fichier, l'administrateur, etc.

8.1.5  Rendre le contenu d'un sous-répertoire invisible

L'astuce qui suit consiste simplement à faire afficher par le serveur Web une page html qui signale au visiteur qu'il n'a rien à faire dans ce sous-répertoire.
Lorsque Apache accède à un sous-répertoire pour satisfaire à la demande d'un navigateur client il commence par vérifier les autorisations d'accès (voir ci-dessus). S'il ne rencontre pas de veto alors il part à la recherche d'un éventuel fichier index.html ou index.php (si PHP est installé). S'il ne trouve pas ce fichier alors il affiche le contenu du sous-répertoire qui apparaît donc en clair pour le visiteur.
Pour éviter que le contenu du sous-répertoire ne s'affiche il suffit donc de créer un fichier index.html ou index.php. Concevoir le contenu de ce fichier de telle sorte qu'il réponde à votre attente, du simple message d'avertissement au script PHP qui va renvoyer de force le visiteur dans le droit chemin. C'est simple et relativement efficace pour un environnement non critique. La solution la plus simple consiste simplement à créer un fichier index.html vide. Le navigateur recevra donc une page blanche. Pas très explicite mais simple et efficace !
Attention, il s'agit là simplement de créer une dissuasion. Nous ne sommes plus dans le domaine de la protection gérée comme ci-dessus. Un utilisateur qui connaîtrait un ou plusieurs noms de fichiers contenus dans ce sous-répertoire pourrait y accéder sans le moindre problème en tapant simplement leurs URL complets ! De grâce, ne construisez pas un site central de banque avec de telles méthodes !

8.2  Sécurisation de Mysql

Un peu comme dans le cas d'Apache cette section est spécifique à MySQL. Il importe peu pour ce qui va suivre qu'Apache soit installé ou non (idem pour PHP). Nous supposerons que les notions de bases du langage SQL sont connues (ben voyons !). La première partie de ce chapitre va en effet faire largement appel à ce langage pour régler la configuration. Attention, nous allons utiliser le client texte MySQL ! Pour commencer ouvrez une fenêtre texte (xterm, rxvt, terminal ou autre) et lancez le client MySQL par :
# mysql -u root (on suppose que vous êtes logué comme root). 

La réponse devrait être immédiate "Welcome to the MySQL Monitor ...." et se terminer par l'invite de commande de MySQL qui est modestement mysql>. Je reproduirais cette invite pour tous les exemples de syntaxe SQL donnés ci-dessous.
Attention, vous êtes logué comme administrateur, tout ce que vous allez faire pourra devenir dramatique en cas d'erreur !
tapez mysql>use mysql; pour préciser au serveur d'utiliser dans ce qui suit la base de données nommée mysql. La réponse devrait se terminer par "Database changed".

8.2.1  Configuration des fichiers d'autorisations d'accès

La protection de MySQL s'articule autour des fichiers d'autorisations (qui constituent eux-même une base de données MySQL) qui définissent très précisément les droits de chaque utilisateur, des informations les plus globales (telle base de donnée est accessible à tel utilisateur) aux plus pointues (la n-ième colonne de telle table est accessible pour tel utilisateur mais seulement pour telle opération). Ces droits sont différenciés, consultation, mise à jour, etc. La base de données qui décrit la structure des autorisations d'accès est contenue dans /var/lib/mysql/mysql/ (dans l'installation Mdk8.2). Cette BDD est créée automatiquement par le script d'installation du package MySQL. Vous pouvez consulter la liste des tables de cette base par mysql>show tables;
Cette commande affiche la liste des tables constituant la BDD.
L'objet du présent document étant de constituer une aide de départ (et non de remplacer la documentation spécialisée) nous ne nous intéresseront dans ce qui suit qu'à une seule table de cette base de données, la table user qui défini les droits d'accès globaux des utilisateurs à l'ensemble des BDD. De même nous n'étudierons que le cas d'une machine isolée servant à la fois de serveur et de client. La configuration en réseau n'est guère plus complexe mais dépasserait le cadre de la présente étude.

Structure de la table user   La structure de la table user est assez simple. Elle contient les champs suivants:

Host char(60) nom de la machine depuis laquelle est fait l'appel
User char(16) login de l'utilisateur
Password char(16) mot de passe codé
Select_priv droits d'effectuer des requêtes sélect (valeur Yes ou No)
Insert_priv...
Update_priv...
Delete_priv...
Create_priv droits d'effectuer une création de table
Drop_priv droits de suppression d'une table
Reload_priv droits de relancer le serveur MySQL
Shutdown_priv droits d'arrêter le serveur MySQL
Process_priv
File_priv
Grant_priv
References_priv
Index_priv
Alter_priv
Table 1: Tableau de la structure de la table user

Cette structure peut être consultée très simplement par mysql>desc user; Son contenu peut être affiché par mysql>select * from user;

Mise à jour de la table user   Cette table contient d'origine (après l'installation décrite dans le document précédent) 4 enregistrements qui définissent les droits de l'administrateur depuis localhost et localhost.localdomain et ceux d'un utilisateur non nommé depuis les mêmes hôtes. L'administrateur root (dont vous utilisez le compte actuellement) a tous les droits, l'utilisateur non nommé aucun, si ce n'est celui d'accéder à la base de données mais sans pouvoir faire la moindre opération. Vous constaterez également que root n'a pas de mot de passe (voir plus haut, cette partie du script a été sautée au moment de l'installation de façon à ne pas bloquer le fonctionnement de phpMyAdmin).

La première étape va consister à supprimer les lignes qui sont inutiles de telle sorte à ne conserver qu'une seule ligne, celle qui correspond à l'administrateur root depuis localhost.
Tapez donc :

 
mysql>delete from user where Host='localhost.localdomain'; 
mysql>delete from user where User=''; 
mysql>select * from user; 

Cette fois la liste devrait contenir le seul enregistrement relatif à root depuis localhost. Pour ajouter un utilisateur lambda procédez comme suit :
mysql>insert into user values('localhost','lambda',password('mdp_lambda'), 'Y','Y','Y','Y','N','N','N','N','N','N','N','N','N','N'); 

Ne comptez pas, il y a 4 'Y' et 10 'N' ! Vous venez de créer un nouvel utilisateur nommé lambda et dont le mot de passe est mdp_lambda (vous mettez bien sûr ce qui vous convient). Attention ce nouvel utilisateur possède des droits sur la base mysql. Afin de créer un utilisateur sans droit, on utilise :
mysql>insert into user values('localhost','lambda',password('mdp_lambda'), 'N','N','N','N','N','N','N','N','N','N','N','N','N','N'); 

La syntaxe de cette ligne mérite quelques commentaires : Vous pouvez maintenant quittez le client mysql en tapant mysql>quit;

Rechargement de la table des autorisations par MySQL   Il reste à vérifier la validité de ce nouvel utilisateur en essayant de se connecter avec ce nouveau login. Mais avant il faut que MySQL actualise la table des autorisations conservée en mémoire et chargée au lancement initial du serveur. Pour cela tapez dans un terminal :

# mysqladmin -uroot flush-privileges -p

Cette commande demande à MySQL de recharger les tables définissant les autorisations d'accès depuis le disque sans pour autant arrêter le serveur.

Une autre solution plus brutale serait d'arrêter le serveur et de le redémarrer en tapant (compte root)

# /etc/rc.d/init.d/mysql stop
# /etc/rc.d/init.d/mysql start

Login avec le nouveau compte   Vous pouvez maintenant vous loguer avec le compte nouvellement créé. Plusieurs possibilités s'offrent à vous :

Ce qui ne marche pas : Voilà, vous êtes maintenant en mesure de modifier efficacement le fichier user pour accorder et retirer des droits à chacun des utilisateurs de votre système. Ce chapitre n'a simplement fait que soulever un coin du voile sur la question. L'étude de l'utilisation des autres fichiers de /var/lib/mysql/mysql/ vous permettra de définir encore mieux ces droits et de créer des droits différenciés par BDD et par utilisateur, voire même par table ou par champ. L'étape suivante s'articulerait autour de la table db. Cette étude de détail sortirait toutefois du cadre fixé ici.

8.2.2  Automatisation des connexions

A ce stade nous pouvons définir autant d'utilisateurs que souhaité. Chacun devra se connecter à MySQL avec la syntaxe $ mysql -u utilisateur -p (utilisateur étant à remplacer par le login). En réponse MySQL demandera le mot de passe correct.

Il peut paraître lourd, alors que GNU/Linux vous a déjà demandé de vous identifier correctement au login, de se re-identifier à nouveau à chaque lancement d'un client MySQL. Cette procédure est heureusement contournable. A chaque lancement d'un client MySQL celui-ci va en effet vérifier la présence des fichiers suivants :

Dès qu'il trouvera un fichier le client MySQL lira les données de configuration qui y sont rangées et ira à la recherche du fichier suivant dans la liste et dans cet ordre. Les données les plus récentes iront à chaque fois écraser les plus anciennes ce qui permet de personnaliser très finement le comportement du client MySQL en fonction des besoins de l'utilisateur. Et parmi ces données, mais vous l'aurez déjà deviné, figurent le mot de passe de connexion au serveur MySQL ! Dans une installation de base aucun de ces fichiers n'existe. Par contre le sous-répertoire /usr/share/mysql/ contient un certain nombre de fichiers exemples nommés my-small.cnf, my-medium.cnf, etc. qui correspondent à des propositions de fichiers de configuration pour différents cas d'utilisation. Les premières lignes de chacun de ses fichiers précisent les domaines d'application.
Pour automatiser le login MySQL pour un utilisateur lambda en se basant sur le modèle medium procéder comme suit : Le tour est joué ! A la prochaine connexion avec le client MySQL celui-ci trouvera le mot de passe et établira une connexion directe en utilisant le login GNU/Linux de l'utilisateur et le mot de passe mémorisé dans /.my.cnf.

Pour vérifier tapez simplement $ mysql pour lancer un client MySQL. La connexion devrait être immédiate. Vérifiez sous quel login vous êtes entré en tapant mysql> select user(); ce qui devrait provoquer l'affichage d'un tableau à une seule cellule titrée user() et contenant une information du genre lambda@localhost.

8.2.3  Contrôle des accès MySQL initiés par des scripts PHP

Un script PHP qui accède à une base de données MySQL le fait dans des conditions fixées par la syntaxe de la commande de connexion. En PHP on obtient une connexion à un serveur MySQL au moyen de la commande mysql_connect().

Celle-ci utilise trois arguments, $host, $user, $password et renvoie une valeur TRUE, 1 si la connexion est établie, FALSE, 0 si celle-ci a échoué.

Le login de connexion ainsi que le mot de passe apparaissent donc en clair dans le script de connexion ce qui est moyennement satisfaisant. Aspect positif le script lui-même n'est jamais envoyé au client puisque PHP s'exécute entièrement sur le serveur (contrairement à JAVA). Il n'y a donc aucune raison pour qu'un visiteur puisse lire ce mot de passe. Oui, mais... il n'y a pas que des visiteurs ``normaux'' ! Une protection supplémentaire (et aussi une simplification si on rédige beaucoup d'applications PHP) est de définir ses variables $host, $user et $password dans un fichier extérieur au script lui-même et d'incorporer ces valeurs au moyen d'une directive include.

Avantage : le fichier qui contient les variables peut être stocké en dehors des sous-répertoires consultés normalement par Apache (hors de l'arborescence /var/www/html/), et protégé par un fichier .htaccess.

Finalement le contrôle d'accès à MySQL via un script PHP découle directement de ce qui a été exposé au chapitre précédent et s'appuie directement sur les règles d'accès à MySQL définies dans la base de données /var/lib/mysql/mysql/. Il peut donc s'avérer souhaitable de créer un compte utilisateur MySQL spécifique aux applications PHP qui tournent sur le serveur. On pourrait aussi imaginer d'en créer plusieurs, 1 par famille de scripts par exemple.

8.3  Sécurisation de PHPMyAdmin

PhpMyAdmin est une petite merveille, un ensemble de scripts PHP, qui permet d'accéder au serveur MySQL en utilisant une interface graphique plus avenante que le spartiate client MySQL en mode texte.

L'installation par défaut (avec un paquetage) conduit à faire de phpMyAdmin un client MySQL avec un login root sans mot de passe (d'où l'intérêt de ne pas mettre, dans un premier temps, de mot de passe au compte root faute de quoi phpMyAdmin ne serait plus en mesure d'accéder au serveur MySQL).

En fait le fonctionnement de phpMyAdmin est réglé par le fichier /var/www/html/phpMyAdmin/config.inc.php3 pour la version 3 de PHP et config.inc.php pour la version 4.
Ce fichier, assez court, contient notamment les lignes suivantes :

 
// The $cfgServers array starts with $cfgServers[1]. Do not use $cfgServers[0]. 
// You can disable a server config entry by setting host to ''. $cfgServers[1]['host'] = 'localhost'; // MySQL hostname 
$cfgServers[1]['port'] = ''; // MySQL port - leave blank for default port 
$cfgServers[1]['adv_auth'] = false; // Use advanced authentication? 
$cfgServers[1]['stduser'] = 'root'; // MySQL standard user (only needed with advanced auth) 
$cfgServers[1]['stdpass'] = ''; // MySQL standard password (only needed with advanced auth) 
$cfgServers[1]['user'] = 'root'; // MySQL user (only needed with basic auth)
$cfgServers[1]['password'] = ''; // MySQL password (only needed with basic auth)
$cfgServers[1]['only_db'] = ''; // If set to a db-name, only this db is accessible 
$cfgServers[1]['verbose'] = ''; // Verbose name for this host - leave blank to show the hostname

Dans le cas ou vous utilisez une version de phpMyAdmin antérieur à la 2.O. Sinon vous aurez ce type de fichier

 
<?php

[...]

/* $Id: config.inc.php,v 1.70 2002/02/10 09:24:47 loic1 Exp $ */
/**
 * Your phpMyAdmin url
 *
 * Complete the variable below with the full url ie
 *    http://www.your_web.net/path_to_your_phpMyAdmin_directory/
 */
$cfgPmaAbsoluteUri = 'http://localhost/phpMyAdmin';


/**
 * Server(s) configuration
 */
// The $cfgServers array starts with $cfgServers[1].  Do not use $cfgServers[0].
// You can disable a server config entry by setting host to ''.
$cfgServers[1]['host']          = 'localhost'; 
// MySQL hostname
$cfgServers[1]['port']          = '';          
// MySQL port - leave blank for default port
$cfgServers[1]['socket']        = '';          
// Path to the socket - leave blank for default socket
$cfgServers[1]['connect_type']  = 'tcp';       
// How to connect to MySQL server ('tcp' or 'socket')
$cfgServers[1]['stduser']       = '';          
// MySQL standard user settings (this user must have read-only
$cfgServers[1]['stdpass']       = '';          
//   access to the "mysql/user" and "mysql/db" tables)
$cfgServers[1]['auth_type']     = 'config';     
// Authentication method (config, http or cookie based)?
$cfgServers[1]['user']          = 'root';      
// MySQL user
$cfgServers[1]['password']      = '';          
// MySQL password (only needed with 'config' auth)
$cfgServers[1]['only_db']       = '';          
// If set to a db-name, only this db is displayed at left frame
                                               
// It may also be an array of db-names
$cfgServers[1]['verbose']       = '';          
// Verbose name for this host - leave blank to show the hostname
$cfgServers[1]['bookmarkdb']    = '';          
// Bookmark db - leave blank for no bookmark support
$cfgServers[1]['bookmarktable'] = '';          
// Bookmark table - leave blank for no bookmark support
$cfgServers[1]['relation']      = '';          
// table to describe the relation between links (see doc)
                                               
//   - leave blank for no relation-links support

$cfgServers[2]['host']          = 'localhost';
$cfgServers[2]['port']          = '';
$cfgServers[2]['socket']        = '';
$cfgServers[2]['connect_type']  = 'tcp';
$cfgServers[2]['stduser']       = '';
$cfgServers[2]['stdpass']       = '';
$cfgServers[2]['auth_type']     = 'config';
$cfgServers[2]['user']          = '';
$cfgServers[2]['password']      = '';
$cfgServers[2]['only_db']       = '';
$cfgServers[2]['verbose']       = '';
$cfgServers[2]['bookmarkdb']    = '';
$cfgServers[2]['bookmarktable'] = '';
$cfgServers[2]['relation']      = '';

$cfgServers[3]['host']          = '';
$cfgServers[3]['port']          = '';
$cfgServers[3]['socket']        = '';
$cfgServers[3]['connect_type']  = 'tcp';
$cfgServers[3]['stduser']       = '';
$cfgServers[3]['stdpass']       = '';
$cfgServers[3]['auth_type']     = 'config';
$cfgServers[3]['user']          = 'root';
$cfgServers[3]['password']      = '';
$cfgServers[3]['only_db']       = '';
$cfgServers[3]['verbose']       = '';
$cfgServers[3]['bookmarkdb']    = '';
$cfgServers[3]['bookmarktable'] = '';
$cfgServers[3]['relation']      = '';

// If you have more than one server configured, you can set $cfgServerDefault
// to any one of them to autoconnect to that server when phpMyAdmin is started,
// or set it to 0 to be given a list of servers without logging in
// If you have only one server configured, $cfgServerDefault *MUST* be
// set to that server.
$cfgServerDefault = 1;                         // Default server (0 = no default server)
$cfgServer        = '';
unset($cfgServers[0]);

[...]

/**
 * Unset magic_quotes_runtime - do not change!
 */
set_magic_quotes_runtime(0);
?>


Le changement le plus important se situe au niveau de la disparition de la directive [adv_auth], qui à été remplacée par la directive auth_type. Le texte de ce fichier semble assez explicite. Il nécessite toutefois une analyse plus détaillée pour bien en comprendre certaines finesses.

$cfgServers[1] désigne le premier serveur MySQL, le seul qui nous intéresse ici (il semblerait qu'il y ait des vicieux qui démarrent plusieurs serveurs.. imaginez un peu ;-)). Le paramètre important est [adv_auth]. Il peut prendre deux valeurs, false (défaut à l'installation) et true. Par contre auth_type peut prendre 3 valeurs :

8.3.1  Configuration avec adv_auth = false

Avec false l'authentification se fait selon une ancienne méthode qui utilise les valeurs de $cfgServers[1]['user'] et $cfgServers[1]['password'] pour s'identifier auprès de MySQL.

L'installation de base résumée ci-dessus reflète cette authentification. En clair phpMyAdmin s'enregistre sous compte root et sans mot de passe. C'est précisément la raison pour laquelle il ne faut surtout pas, en cours d'installation de MySQL, donner suite à la proposition du script de définir un mot de passe administrateur (voir http://jeanmarc.lichtle.free.fr/Apache_PHP_MySQL.html). Définir un mot de passe à ce stade de l'installation bloquerait le fonctionnement ultérieur de phpMyAdmin. Pour le vérifier faites simplement l'essai de fixer un mot de passe pour root dans MySQL. La syntaxe SQL est la suivante (mais vous l'aurez déjà deviné) :

 
mysql> update user set Password=password('mdp_root') where user = 'root'; 

Un petit coup de # mysqladmin -uroot flush-privileges -p (y'en a qui avaient oublié !?) et voilà le mot de passe administrateur pris en compte par le serveur MySQL. Pour la petite histoire c'est la dernière fois que vous tapez cette commande avec cette syntaxe simple. Maintenant que root a un mot de passe dans MySQL il faudra utiliser la syntaxe # mysqladmin -uroot -p flush-privileges, ce qui va provoquer la demande du mot de passe par le serveur.

Et maintenant adieu phpMyAdmin, ça ne marche plus ! Seulement voilà, arrivé à ce stade de notre étude nous savons comment faire prendre en compte ce mot de passe par phpMyAdmin. Il suffit de l'incorporer au fichier de configuration /var/www/html/phpMyAdmin/config.inc.php3 à la ligne $cfgServers[1]['password'] = ''.
Au prochain lancement de phpMyAdmin le fichier de configuration va être pris en compte et tout va rentrer dans l'ordre, la connexion s'effectuant à nouveau de façon directe... Bon, ça ne marche pas ? Ne vous affolez pas ! Je fais le pari que vous avez fait des essais de .htaccess ou de httpd.conf sur le sous répertoire de phpMyAdmin et qu'il reste des traces des essais effectués précédemment. Supprimez (ou renommez) l'éventuel fichier .htaccess situé dans le sous répertoire /var/www/html/phpMyAdmin/ et/ou mettez des commentaires (#) aux éventuelles lignes ajoutées à /etc/httpd/conf/httpd.conf. Attention de relancer Apache si vous modifiez httpd.conf !

8.3.2  Configuration avec adv_auth=true

L'authentification avancée diffère légèrement du cas précédent en ce que le login et le mot de passe de l'utilisateur qui lance phpMyAdmin sont demandés au lancement. Il n'y a plus un login de connexion unique, celui-ci peut changer en fonction des informations données par l'utilisateur qui lance phpMyAdmin. Ces informations sont ensuite comparées à la base de données des utilisateurs autorisés par MySQL. La connexion est établie si les informations sont correctes. Il faut toutefois établir une première connexion de façon à avoir un accès temporaire à la table user. C'est à cette fin que la configuration prévoit un compte défini par $cfgServers[1]['stduser'] et $cfgServers[1]['stdpass'], ces deux variables devant permettre la vérification des droits d'accès. Il va sans dire que le [stduser] désigné ici devra avoir des droits suffisants pour lire la table user. Cette authentification offre au minimum deux avantages : Pour le fun, et c'est une excursion vers l'étude de la configuration avancée des droits d'accès MySQL on peut même limiter encore plus les droits de cet utilisateur spécial. Il suffit de ne lui donner aucun droit dans la table user (14 fois 'N') et de lui créer une ligne dans la table db. Cherchez bien, la syntaxe est extrêmement proche de celle qui ajoute un utilisateur dans user, il suffit de préciser cette fois que ces droits s'applique spécifiquement à la base de données mysql. L'utilisateur 'phpMyAdmin' aura donc uniquement le droit de lire le contenu des tables user, db etc.. qui constituent la base mysql. Vous pouvez même aller plus loin dans le raisonnement et limiter les droits strictement à la table user. Mais là c'est une autre affaire, je sens que vous allez passer quelques heures sur l'étude détaillée des droits d'accès MySQL.

8.3.3  Les modes auth_type= http, cookie et config

Mode d'authentification 'http' : Mode d'authentification 'cookie' : Mode d'authentification 'config' :

8.3.4  Exemple de configuration avec http

Dans ce cas c'est la base de donnée Mysql qui donne les droits d'accéder à PhpMyAdmin. Il s'agit donc de bien configurer les utilisateurs standards et administrateurs de la base.

La première étape va consister à supprimer les lignes qui sont inutiles de telle sorte à ne conserver qu'une seule ligne, celle qui correspond à l'administrateur root depuis localhost.
Tapez donc :

 
mysql>delete from user where Host='localhost.localdomain'; 
mysql>delete from user where User=''; 
mysql>select * from user; 

Cette fois la liste devrait contenir le seul enregistrement relatif à root depuis localhost.

Par ailleurs, dans la plupart des installations de Mysql via les paquets binaires, aucun mot de passe n'est affecté à l'administrateur de la base de données (root). Il s'agit alors d'an affecté un via la commande suivante :

mysqladmin -p -uroot password le_mot_de_passe

s'il y a un mot de passe déjà défini, et
mysqladmin -uroot password le_mot_de_passe

s'il n'y a rien de définit.

Pour cela on aura affecter un mot de passe à chaque utilisateur à l'aide de la commande :

mysqladmin -p -umysql password

si l'on a crée un utilisateur mysql. On vérifiera que cet utilisateur ne possède aucun droit sur la base Mysql. Sinon il est nécessaire de modifier ses droits afin qu'il devienne un utilisateur standard.
mysql>insert into user values('localhost','lambda',password('mdp_lambda'),
 'Y','Y','Y','Y','N','N','N','N','N','N','N','N','N','N'); 

et l'on n'oubliera pas le bon vieux
# mysqladmin -uroot flush-privileges -p

mysql> update user set Select_priv = 'N', Insert_priv = 'N', 
Update_priv = 'N', Delete_priv = 'N'  where user ='mysql';
Query OK, 1 row affected (0.33 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> 

si l'utilisateur avais déjà des droits. Nous allons maintenant créer une base dont le propriétaire sera le nouvel utilisateur mysql. On se logue sur la base en tant qu'administrateur.
[yann@ulysse stroustrup]$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 111 to server version: 3.23.47

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> create database tp_base;
Query OK, 1 row affected (0.00 sec)

mysql> use tp_base;
Database changed

mysql>

On va donné tous les droits à mysql, sur cette base.
mysql> GRANT ALL PRIVILEGES ON test_base.* to mysql@localhost;
Query OK, 0 rows affected (0.00 sec)

mysql>

Maintenant un petit
# mysqladmin -uroot flush-privileges -p

pour que tout soit à jour. Il est alors possible de se logué sur la base via
[yann@ulysse stroustrup]$ mysql -p -u mysql tp_base
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11 to server version: 3.23.46

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

Et de remplir la base. Mais là n'est pas notre propos. Nous allons la remplir via phpMyAdmnin.

Tout le travail précédent a servi à bien différencier un utilisateur standard comme mysql qui ne pourra travailler que sur la base tp_base et l'administrateur qui lui peut faire ce qu'il veut.

En fait, ce qu'il va se passer, c'est que lors de la connection à phpMyAdmin, suivant le login et le mot de passe donné, les utilisateurs auront accès aux seules bases de données sur lesquelles ils ont des droits.

Pour cela il est nécessaire de configurer le fichier config.inc.php qui se trouve dans le repertoire de base de phpMyAdmin qui se trouve dans /var/www/html/phpMyAdmin sur une Mandrake 8.2.

Nous allons donc utiliser une authentification http. Ce qui est interressant c'est que plus aucun mot de passe n'apparaitra dans le fichier config.inc.php.

<?php
/* $Id: config.inc.php,v 1.62 2001/12/23 23:05:23 lem9 Exp $ */


/**
 * phpMyAdmin Configuration File
 *
 * All directives are explained in Documentation.html
 */


/**
 * Bookmark Table Structure
 *
 * CREATE TABLE bookmark (
 *  id int(11) DEFAULT '0' NOT NULL auto_increment,
 *  dbase varchar(255) NOT NULL,
 *  user varchar(255) NOT NULL,
 *  label varchar(255) NOT NULL,
 *  query text NOT NULL,
 *  PRIMARY KEY (id)
 * );
 *
 */


/**
 * Your phpMyAdmin url
 *
 * Complete the variable belowREADME with the full url ie
 *    http://www.your_web.net/path_to_your_phpMyAdmin_directory/
 */
$cfgPmaAbsoluteUri = '';


/**
 * Server(s) configuration
 */
// The $cfgServers array starts with $cfgServers[1].  Do not use $cfgServers[0].
// You can disable a server config entry by setting host to ''.
$cfgServers[1]['host']          = 'localhost'; 
// MySQL hostname
$cfgServers[1]['port']          = '';          
// MySQL port - leave blank for default port
$cfgServers[1]['socket']        = '';          
// Path to the socket - leave blank for default socket
$cfgServers[1]['connect_type']  = 'tcp';       
// How to connect to MySQL server ('tcp' or 'socket')
$cfgServers[1]['stduser']       = '';          
// MySQL standard user settings (this user must have read-only
$cfgServers[1]['stdpass']       = '';          
//   access to the "mysql/user" and "mysql/db" tables)
$cfgServers[1]['auth_type']     = 'http';     
// Authentication method (config, http or cookie based)?
$cfgServers[1]['user']          = '';      
// MySQL user
$cfgServers[1]['password']     README = '';          
// MySQL password (only needed with 'config' auth)
$cfgServers[1]['only_db']       = '';          
// If set to a db-name, only this db is displayed at left frame
                                               
// It may also be an array of db-names
$cfgServers[1]['verbose']       = '';          
// Verbose name for this host - leave blank to show the hostname
$cfgServers[1]['bookmarkdb']    = '';          
// Bookmark db - leave blank for no bookmark support
$cfgServers[1]['bookmarktable'] = '';          
// Bookmark table - leave blank for no bookmark support
[snip]
...
[snip]
/**
 * Unset magic_quotes_runtime - do not change!
 */
set_magic_quotes_runtime(0);
?>

Il ne reste qu'à l'enregistrer.

Attention : apparement avec la version 2.2.6 de PhpMyAdmin, il n'est plus possible de laisser le champ $cfgPmaAbsoluteUri vide. En effet il est alors nécessaire de la remplir avec $cfgPmaAbsoluteUri= 'http://localhost/phpMyAdmin/';, sinon phpMyAdmin renvoie un message d'erreur.

À cet instant nous avons la configuration suivante :

Et voici le résultat en images.

images/connect_phpmyadmin.jpg
Figure 6: Connection aux bases de données via phpMyAdmin

Si on se connecte en tant que mysql,nous n'avons accès qu'à la base tp_base,

images/connect_phpmyadmin2.jpg
Figure 7: Fenêtre d'authentification

images/connect_phpmyadmin3.jpg
Figure 8: Connection à la base tp_base

par contre si on se connecte en tant que root, nous avons accès à toutes les bases, ainsi qu'à la base mysql.

images/connect_phpmyadmin4.jpg
Figure 9: Fenêtre d'authentification

images/connect_phpmyadmin5.jpg
Figure 10: Connection aux bases de Mysql

8.4  Le petit bréviaire

Je ne sais pas si vous êtes comme moi mais j'ai besoin de prendre des notes pour retrouver rapidement les informations vitales dans un document aussi touffu que celui-ci. Parmi les informations qu'il me semble intéressant de résumer ici je dresse à toutes fins utiles la liste des fichiers et répertoires qui ont été évoqués ci-dessus (dans leur ordre d'apparition en scène) :

Répertoire/fichier Fonction
/var/www/html/ Base arborscence site Web
/var/www/html/phpMyAdmin/config.inc.php3 Configuration de phpMyAdmin
/var/lib/mysql/mysql/ Base de données des droits d'accès
/var/lib/mysql/my.conf Configuration de base de MySQL (optionnel)
/etc/httpd/auth/ Rangement des fichiers d'authentification par .htaccess
/etc/httpd/conf/httpd.conf Configuration serveur Apache
/etc/rc.d/init.d/httpd Lancement du serveur Apache option restart
/etc/rc.d/init.d/mysql Lancement du serveur MySQL opt stop ou start
/etc/my.conf Configuration de base de MySQL (optionnel)
/.my.conf Configuration de base de MySQL (opt. spécif. util.)
/usr/share/mysql/ Contient des exemples de fichier my.cnf
/var/log/httpd/ Contient les fichiers log
Table 2: Tableau de la structure de la table user

Je précise à nouveau que ce document s'applique au cas d'une installation en environnement Mandrake Linux 8.2 telle que décrite dans un document identifié plus haut. Un système qui serait basé sur une autre distribution et/ou qui utiliserait des versions d'Apache, PHP ou MySQL qui auraient été compilées par l'utilisateur pourrait utiliser d'autre répertoires pour stocker les différentes informations. L'essentiel est d'obtenir un ensemble cohérent.

8.5  Conclusion

L'exposé ci-dessus devait vous mettre en situation d'appréhender sérieusement la question assez complexe (mais oh combien stratégique) du contrôle des accès sur un serveur Apache PHP MySQL. J'espère avoir atteint cet objectif en montrant comment structurer la réflexion : Il est évident qu'un sujet aussi vaste ne peut être qu'effleuré en quelques pages aussi je vous renvoie vers la littérature plus complète (livres, HowTo, pages man etc..) sur les différents points abordés. J'espère sincèrement que ce document servira un jour à quelqu'un. Sa rédaction est de toute façon justifiée par le simple fait que l'exercice m'a obligé à mettre mes connaissances et mes notes au propre, à tester pas à pas toutes mes propositions. J'en suis donc le premier lecteur. N'hésitez pas à me faire part de votre avis sur l'intérêt de cette étude. Toute suggestion d'amélioration sera bienvenue.

9  PHP et MySQL

Maintenant que le trio Apache, Mysql et Php est installé sur votre machine, on va pouvoir les mettrent en uvre de concert.
Je considère que vous connaissez un minimum le langage HTML. En effet vous en aurez besoin pour la suite. La langage php possède des fonctionnalité permettant de l'interfacé avec des bases de données. Ces fonctionnalités on été activées lors de la compilation de notre serveur Apache.

On peut donc utiliser Mysql avec des scripts Php.

9.1  Connection à la base

Les fonctions Mysql de Php vont vous permettre de vous connecter à la base de votre choix grâce à un identifiant et un mot de passe. La fonction de connexion retourne un identitfiant de connexion (identifiant mysql et sont mot de passe) :
$dbh=mysql_connect("localhost","mysql","mot_de_passe");

La fonction mysql_connect prend trois arguments en paramètre : l'hôte ou réside le serveur (dans notre cas la base de données est située sur le même serveur qu'Apache), un identifiant d'utilisateur Mysql (ici il s'agit de mysql qui possède la base tp_base) et son mot de passe. La fonction renvoie un paramètre dans $ dbh qui est l'identifiant de connexion. La valeur contenue dans $ dbh importe peu, sauf si cette dernière est nulle. En effet dans ce cas une erreur s'est produite lors de la connexion à la base.

Cette technique est valable pour des tests, mais si vous envisagez une sérieuse exploitation de la base de données via php, il est ,password('nécessaire de programmer de tel manière que le mise à jour d'un mot de passe ne demande pas la modification de tous les fichiers faisant référence à la base de donnée.

Pour cela nous allons placer les paramètres de la base dans un fichier séparé, par exemple base.php :

<?
$DBdatabase='tp_base';
$DBuser='mysql';
$DBpass='mot_de_passe'
?>

Dans ce fichier, nous définissons trois variables qui contiendront les données relatives à la connexion à la base : le nom de la base, l'identifiant et le mot de passe.

Ensuite au lieu d'utiliser

$dbh=mysql_connect("localhost","mysql","mot_de_passe");

dans le fichier gérant la connexion, on insère
<?
require("base.php");
$dbh=mysql_connect("localhost","$DBuser","$DBpass");
?>

La directive require permet de charger le contenu d'un fichier php dans le fichier courant, à la manière d'un # include en C. Dans ce cas, après l'appel au fichier base.php, les variables $DBdatabase, $DBuser et $DBpass seront disponibles.

Cette directive peut aussi être utilisée dans le cas ou du code html se retrouve dupliqué un grand nombre de fois.

9.2  Première requète

Ce premier fichier php aura pour but l'interrogation et l'affichage de la listes des auteurs contenus dans la base tp_base. Voici le code source du fichier final :
<html>
<body>
<?
require("base.php");
$dbh=mysql_connect("localhost","$DBuser","$DBpass");
if (!$dbh)
	{
	echo "<font color=\"#FF0000\">ERREUR! Impossible de se connecter à la base
	$DBdatabase.</font><br>";
	echo "</body></html>";
	exit;
	}
$res=mysql_db_query("$DBdatabase","select nom, prenom from auteurs order by nom;", $dbh);	
$errno=mysql_errno($dbh);
if ($errno!=0)
	{
	$erreur=mysql_error($dbh);
	echo "<font color=\"#FF0000\">$erreur.</font><br>";
	mysql_close($dbh);
	echo "</body></html>";
	exit;
	}
 
$nbr_ligne=mysql_num_rows($res);
$nbr_champ=mysql_num_fields($res);
/*
echo "res vaut $res";
echo "nb ligne vaut $nbr_ligne";
*/
/*
echo "<table border=2 cellpadding=2 width=\"50%\">";
for($i=0;$i<$nbr_ligne;$i++)
	{
	$row=mysql_fetch_row($res);
	echo "<tr><td>$row[0]</td><td>$row[1]</td></tr>";
	}
echo "</table>";	
*/
echo "<table border=2 cellpadding=2 width=\"50%\">";
for($i=0;$i<$nbr_champ;$i++)
	{
	printf("<th>%s</th>",mysql_field_name($res,$i));
	}
for($i=0;$i<$nbr_ligne;$i++)
	{
	$row=mysql_fetch_row($res);
	echo "<tr>";
	foreach($row as $col)
		{
		if(!$col) $col="&nbsp";
		echo "<td>$col</td>";
		}
	echo "</tr>";	
	}
echo "</table>";	


?>
</body>
</html>

Quelques explications s'imposent peut être
Le morceau de code
if (!$dbh)
	{
	echo "<font color=\"#FF0000\">ERREUR! Impossible de se connecter à la base 
	$DBdatabase.</font><br>";
	echo "</body></html>";
	exit;
	}

teste une eventuelle erreur lors de la connexion à la base de données et termine le fichier html le cas échéans. Si tout se passe bien, nous passons à la requète proprement dite.
$res=mysql_db_query("$DBdatabase","select nom, prenom from auteurs order by nom;", $dbh);	
$errno=mysql_errno($dbh);
if ($errno!=0)
	{
	$erreur=mysql_error($dbh);
	echo "<font color=\"#FF0000\">$erreur.</font><br>";
	mysql_close($dbh);
	echo "</body></html>";
	exit;
	}

La fonction mysql_db_query prend trois paramètres : Elle renvoie dans la variable $ res un identifiant ou un objet résulat. Attention cette variable n'est pas affichable directement. Ici encore on teste la présence d'une erreur. Comme il n'est pas possible de tester directement la variable $ res, on utilisa la fonction mysql_errno en lui l'identifiant de la connexion comme paramètre. Cette fonction retourne un numéro d'erreur ou 0 si tout s'est bien passé. Il nous suffit alors de tester la valeur de $ errno et d'afficher le message d'erreur renvoyer par la fonction mysql_errno sans oublier de terminer la page html.

Le résultat de la requète est une table qu'il convient de traiter. Il faut alors utiliser des fonctions spécifiques. On va tout d'abord se renseigner sur le nombre de lignes et de colonnes contenues dans cette table.

$nbr_ligne=mysql_num_rows($res);
$nbr_champ=mysql_num_fields($res);

La fonction mysql_num_rows renvoie le nombre de lignes de l'identifiant passé en paramètre. La fonction mysql_num_fields permet de connaitre le nombre de colonnes contenues dans la table résultat.

En suite nous pouvons récupérer les nomps des champs de la table grâce à la fonction mysql_field_name qui s'utilise de la manière suivante :

$nom_champ=mysql_field_name($res,numero_du_champ);

Il nous reste à récuperer les valeurs contenues dans les lignes de la tables. Pour cela nous allons utiliser la fonction mysql_fetch_rows. Cette dernière permet d'extraire une ligne de résultat via l'identifiant de connexion.

Le code suivant permet de placer le resultat dans des case de tableau :

for($i=0;$i<$nbr_ligne;$i++)
	{
	$row=mysql_fetch_row($res);
	echo "<tr><td>$row[0]</td><td>$row[1]</td></tr>";
	}"

le code suivant permet de s'adapter à tout type de tableau :
for($i=0;$i<$nbr_ligne;$i++)
	{
	$row=mysql_fetch_row($res);
	echo "<tr>";
	foreach($row as $col)
		{
		if(!$col) $col="&nbsp";
		echo "<td>$col</td>";
		}
	echo "</tr>";	
	}

10  Formulaire, PHP et Mysql

La suite au prochain numéro.

Voila c'est terminé pour cette article. Si vous avez des commentaires, des corrections, faites le moi savoir par l'intermédiaire de l'adresse suivante morere@lasc.univ-metz.fr.


Footnotes:

1voir plus loin le chapitre Automatisation des connexions, il sera possible d'automatiser l'indication du mot de passe et donc de se connecter en utilisant cette syntaxe.


File translated from TEX by TTH, version 3.05.
On 12 Jul 2002, 17:18.