Skip to content
Snippets Groups Projects
Commit c0c9c8ce authored by BURCKEL Luc's avatar BURCKEL Luc
Browse files

Merge branch 'master' of https://git.unistra.fr/W31/w31

parents b6b5b72b fe3e2dd6
Branches
No related merge requests found
Serveur PHP local
=================
Pour l'environnement de travail, l'utilisation d'une usine à gaz comme LAMP ou WAMP est inutile : vous n'avez besoin que de PHP.
Installation sur une ordinateur personnel
-----------------------------------------
### Sous windows
**L'utilisation d'une distribution Linux est fortement recommandée.** Il n'y a pas de méthode "simple" sous Windows. Deux solutions :
1. Installer une distribution Linux en Dual Boot
2. Installer une machine virtuelle avec une distribution Linux => ici [un tuto pour installer Ubuntu avec Hyper-V](https://www.windowscentral.com/how-run-linux-distros-windows-10-using-hyper-v)
### Sous Linux
Il vous faut les droits root pour installer l'ensemble des paquets dont vous aurez besoin en une seule commande :
```bash
$ sudo apt install php sqlite3 php-sqlite3 sqlitebrowser composer
```
Utilisation
-----------
> *Cette procédure remplace l'utilisation de `public_html` et `webetu`.*
Ce qui suit peut être réalisé :
- sur votre ordinateur personnel si vous avez réalisé l'installation de la section précédente
- sur un bureau à distance de l'IUT depuis `troglo`, `phoenix` ou `cannette`
### Lancement d'un serveur local
La procédure à suivre pour lancer un serveur PHP local est détaillée [dans la doc de PHP](https://www.php.net/manual/fr/features.commandline.webserver.php) dont voici un résumé :
0. On suppose que le répertoire `/chemin/vers/mon/repertoire/de/TP/` sera la racine de l'ensemble des fichiers de votre TP.
1. Ouvrir un terminal
2. Lancer un serveur local dont la racine est ce répertoire :
```bash
$ php -S localhost:port -t /chemin/vers/mon/repertoire/de/TP/
```
avec `port` un entier compris entre 1025 et 65535. Si vous avez un message d'erreur, essayez un autre port.
### Accéder au serveur local depuis un navigateur
Pour visualiser le rendu d'un fichier PHP par le serveur que vous avez lancé, il suffit d'ouvrir un navigateur à cette URL :
**`http://localhost:port`**
et d'ajouter son chemin à la fin de l'URL.
##### Exemples :
| Fichier à visualiser | URL |
|--------------------------------------------------------|----------------------------------------------|
| `/chemin/vers/mon/repertoire/de/TP/signin.php` | `http://localhost:port/signin.php` |
| `/chemin/vers/mon/repertoire/de/TP/rep1/rep2/test.php` | `http://localhost:port/rep1/rep2/signin.php` |
......@@ -39,23 +39,23 @@ Exercice 2 - Générer une liste
2. Écrivez un fichier PHP `listeGet.php` similaire à `liste.php`, où le
nombre d'items à générer est disponible dans **la variable `nbItems` du tableau `$_GET`**. Testez avec Postman et un navigateur. Pensez à ajouter un test pour vérifier que votre variable est un entier et transtypez-la (cast).
3. Écrire un fichier PHP `listePost.php` similaire à `liste.php`, où le
3. Écrivez un fichier PHP `listePost.php` similaire à `liste.php`, où le
nombre d'items à générer est disponible dans **la variable `nbItems` du tableau `$_POST`**. Testez avec Postman.
4. Tester le 3. avec votre navigateur. Pour cela, créez un fichier PHP contenant un **formulaire** avec `listesPost.php` pour action.
4. Testez le 3. avec votre navigateur. Pour cela, créez un fichier PHP contenant un **formulaire** avec `listesPost.php` pour action.
Exercice 3 - Compteur de visites en session
-------------------------------------------
1. Écrire un fichier PHP `counter.php` qui :
1. Écrivez un fichier PHP `counter.php` qui :
- crée ou rétablit une session PHP pour le client
- initialise ou incrémente la variable `$counter` qui sert de compteur
- affiche le nombre de fois que le fichier a été demandé.
Testez avec Postman et le navigateur en appellant plusieurs fois la page `counter.php`. Le chiffre indiqué doit augmenter de 1.
2. Écrire un fichier PHP `resetCounter.php` qui :
2. Écrivez un fichier PHP `resetCounter.php` qui :
1. réinitialise le compteur présent dans la session
2. effectue une demande de redirection vers le fichier `counter.php` (regardez la doc de la directive [`header`](http://php.net/manual/fr/function.header.php)).
......
TP3.md 0 → 100644
TP3 - Gestion d'utilisateurs et BDD
===================================
Dupliquez votre répertoire `TP2` dans un nouveau répertoire `TP3` dans lequel nous allons modifier progressivement les fichiers.
Objectifs
---------
Cet exercice vous propose de mettre en place une gestion des utilisateurs dans une base de données SQLite.
> **Note** : il est fortement recommandé d'avoir réalisé l'exercice 6 du TP2 afin de transmettre les message d'erreur de PHP au client.
Exercice 1 : Mise en place de la BDD
------------------------------------
1. Créez un fichier vide `tp3.db`.
2. Utilisez `sqlite3` ou `sqlitebrowser` pour créer une table `Users` permettant de stocker les logins et mots de passe des utilisateurs. Réfléchissez bien aux champs et attributs des champs : auto-increment, unique, null, etc.
3. Ajoutez manuellement plusieurs utilisateurs.
Utilisation de `sqlite3` en ligne de commande :
```bash
$ sqlite3 tp3.db
sqlite> CREATE TABLE ... ;
sqlite> INSERT INTO ... ;
sqlite> .exit
```
Exercice 2 : Déclaration de la BDD
----------------------------------
1. Supprimez toutes les instructions du fichier `bdd.php`
2. Créez une variable `$sqliteFile` qui contient le chemin absolu vers `tp3.db` **sur le serveur PHP que vous utilisez** (utiliser [`$_SERVER['DOCUMENT_ROOT']`](https://www.php.net/manual/fr/reserved.variables.server.php)).
3. Ajoutez un test d'existence du fichier (voir [`file_exists`](https://www.php.net/manual/fr/function.file-exists.php)) et si ce n'est pas le cas, propagez une `Exception` qui indique que le fichier de BDD n'existe pas.
4. Créez une variable `$SQL_DSN` qui correspond au paramètre de la construction d'un objet PDO (voir [le cours](http://adrien.krahenbuhl.fr/courses/IUTRS/W31/CM2) et [la documentation PHP](https://www.php.net/manual/fr/book.pdo.php)).
Exercice 3 : Authentification
-----------------------------
Il s'agit de modifier le fichier `authenticate.php` pour remplacer l'utilisation du tableau `$users` par la BDD `tp3.db` en utilisant **PDO**.
1. Créez un objet PDO en utilisant les informations contenues dans `bdd.php`.
2. Construisez et exécutez une **requête préparée** permettant de récupérer le mot de passe de l'utilisateur.
3. Adaptez les vérifications suivantes du TP2 :
- que l'utilisateur existe (i.e. que le résultat contient des données).
- que le mot de passe transmis en POST correspond au mot de passe trouvé dans la BDD.
> **Note** : Toutes les erreurs possibles doivent déclencher une demande de redirection vers `signin.php` et mettre à jour le messages d'erreur de variable de session `message`.
Exercice 4 : Inscription
------------------------
1. Écrivez un nouveau fichier `signup.php` qui propose un formulaire d'inscription pour un nouvel utilisateur (avec mot de passe et confirmation de mot de passe) et le soumet à la page `adduser.php`.
2. Écrivez un nouveau fichier `adduser.php` qui :
- vérifie que la méthode HTTP utilisée est `POST`
- vérifie et sécurise les champs du formulaire de `signup.php`
- vérifie que le mot de passe et sa confirmation sont identiques
- tente d'insérer le nouvel utilisateur avec une **requête préparée** :
- si la requête s'est bien passée, il demande une redirection vers `signin.php`
- sinon il demande une redirection vers `signup.php`
3. Pour plus de navigabilité, ajoutez sur la page `signin.php` un lien vers `signup.php`, et réciproquement.
> **Note** : Si vous avez fait l'exercice 6 du TP2, vous pouvez ajouter les messages d'erreur et de réussite à la variable de session `message`.
Exercice 5 : Mots de passe cryptés
----------------------------------
Actuellement les mots de passe sont codés en clair dans votre base de données. Vous allez mettre en place le chiffrement (et le décryptage) des mots de passe.
> **Note 1** : Ce serait le bon moment pour faire un commit Git de votre 1ère version fonctionnelle de ce TP.
> **Note 2** : Si tout a bien été fait jusque là, les questions 2. et 3. de cet exercice nécessitent de ne changer **qu'une seule ligne** dans chacun des fichiers.
1. Supprimez de votre BDD tous les utilisateurs inscrits, via `sqlite3` ou `sqlitebrowser`.
2. Modifiez le fichier `adduser.php` afin qu'il enregistre le mot de passe chiffré avec la fonction PHP [`password_hash`](http://php.net/manual/fr/function.password-hash.php).
3. Modifiez le fichier `authenticate.php` pour qu'il compare le mot de passe du formulaire avec celui récupéré dans la BDD à l'aide de la fonction [`password_verify`](http://php.net/manual/fr/function.password-verify.php).
Exercice 6 (bonus) : Vérification des mots de passe côté client
---------------------------------------------------------------
En théorie, la vérification de la similarité des deux mots de passe s'effectue aussi côté client, en Javascript, afin de réduire les requêtes inutiles.
1. Dans `signup.php`, écrivez une fonction javascript `checkPassword` qui récupère le contenu des `input` du mot de passe et de sa confirmation et les compare. Utilisez la fonction [`setCustomValidity`](https://developer.mozilla.org/fr/docs/Web/API/HTMLSelectElement/setCustomValidity) pour mettre à jour la validité du champ de confirmation.
2. Faite exécuter la fonction `checkPassword` à chaque saisie d'un nouveau caractère dans le champ de confirmation. Regardez du côté de l'attribut HTML [`oninput`](https://developer.mozilla.org/fr/docs/Web/API/GlobalEventHandlers/oninput).
Pour les plus rapides
---------------------
- Niveau 1 : Mise en place de fonctions utilitaires pour la redirection et la vérification de la méthode HTTP utilisée dans un fichier `helpers.php`. Pensez au typage !
- Niveau 2 : Ajoutez un fichier de style CSS pour mettre en forme votre formulaire.
- Niveau 3 : Utilisez [Bootstrap](https://getbootstrap.com) pour mettre en forme vos différentes pages.
TP4.md 0 → 100644
TP4 - Gestion d'utilisateurs et POO
===================================
Dupliquez votre répertoire `TP3` dans un nouveau répertoire `TP4` dans lequel nous allons modifier progressivement les fichiers.
Objectifs
---------
Ce TP propose :
- de mettre en place l'inscription des utilisateurs dans une base de données SQLite,
- de mettre en place le paradigme de POO.
Exercice 1 : Modification du mot de passe
-----------------------------------------
Vous allez ajouter la fonctionnalité de changement de mot de passe avec deux nouveaux fichiers : la vue `formpassword.php` et le contrôleur `changepassword.php`.
1. Créez un nouveau fichier `formpassword.php` contenant un formulaire avec deux champs : un nouveau mot de passe et sa confirmation. Ce formulaire a pour cible `changepassword.php`.
2. Assurez-vous que ce formulaire soit proposé uniquement si l'utilisateur est connecté. Si ce n'est pas le cas, redirigez-le vers `signin.php`.
3. Créez un nouveau fichier `changepassword.php` qui :
- vérifie que l'utilisateur est connecté
- vérifie que la méthode HTTP utilisée est `POST`
- vérifie et sécurise les champs du formulaire de `formpassword.php`
- vérifie que le mot de passe et sa confirmation sont identiques
- tente de changer le mot de passe de l'utilisateur dans la BDD avec une **requête préparée** :
- si la requête s'est bien passée, il demande une redirection vers `account.php`
- Sinon il demande une redirection vers `formpassword.php`.
4. Pour plus de navigabilité, ajoutez un lien vers `formpassword.php` sur la page `account.php`, et réciproquement.
> **Note** : Pensez à mettre à jour la variable de session `message`.
Exercice 2 : Suppression d'un utilisateur
-----------------------------------------
1. Ajoutez un lien vers `deleteuser.php` sur la page `account.php`.
2. Écrivez un nouveau fichier `deleteuser.php` qui :
- vérifie que l'utilisateur est connecté
- tente de supprimer l'utilisateur de la BDD avec une **requête préparée** :
- si la requête s'est bien passée, il supprime la session et demande une redirection vers `signin.php`.
- sinon il demande une redirection vers `account.php`.
> **Note** : Pensez à mettre à jour la variable de session `message`.
Exercice 3 : Passage en POO - Les bases
---------------------------------------
Cet exercice va vous permettre de créer une classe `User` faisant le lien entre votre BDD et le reste de votre code.
1. Créez un répertoire `models`.
2. Déplacer dans `models` le fichier `bdd.php`.
3. Copiez dans `models` le fichier [`MyPDO.php`](corriges/TP4/models/MyPDO.php).
4. Créez dans `models` un fichier `User.php` qui contient la déclaration de la classe `User` avec :
- deux attributs privés pour le login et le mot de passe avec leurs getters/setters
- un attribut privé constant `USER_TABLE` contenant le nom de la table des utilisateurs à utiliser dans les champs `FROM` des requêtes SQL
- un constructeur prenant en paramètre :
- un login
- un mot de passe avec une valeur par défaut `null`
Exercice 4 : Passage en POO - Authentification
----------------------------------------------
1. Dans la classe `User`, écrivez une méthode publique `exists`, sans paramètre, qui effectue les étapes du fichier `authenticate.php` relatives à la BDD, c'est-à-dire :
- faire une requête vers la BDD pour récupérer l'utilisateur dont le login correspond à l'attribut du login de la classe
- déclencher une `Exception` si la requête échoue
- retourner vrai si l'utilisateur existe et que le mot de passe correspond, faux sinon.
**Attention** : pour accéder à l'objet PDO, utilisez la méthode statique `pdo()` de la classe `MyPDO`.
2. Modifiez le fichier `authenticate.php` en remplaçant tout ce qui concerne les requêtes vers la BDD par :
- la création d'un objet `User` à partir des variables récupérées en POST
- l'utilisation de la méthode `exists` pour vérifier si l'utilisateur existe dans la BDD.
> **Note 1** : "Try-catchez" toutes les exceptions pouvant être déclenchées par l'appel à la méthode `exists()`.
> **Note 2** : Utilisez à bon escient l'attribut `USER_TABLE`.
Exercice 5 : Passage en POO - Ajout d'un utilisateur
----------------------------------------------------
1. Dans la classe `User`, écrivez une méthode publique `create`, sans paramètre, qui effectue les étapes du fichier `adduser.php` relatives à la BDD, c'est-à-dire :
- faire une requête vers la BDD pour insérer l'utilisateur `$this`
- déclencher une `Exception` si la requête échoue
2. Modifiez le fichier `adduser.php` en remplaçant tout ce qui concerne les requêtes vers la BDD par :
- la création d'un objet `User` à partir des variables récupérées en POST
- l'utilisation de la méthode `create` pour insérer l'utilisateur dans la BDD.
> **Note** : "Try-catchez" toutes les exceptions pouvant être déclenchées par l'appel à la méthode `create()`.
Exercice 6 : Passage en POO - Changement de mot de passe
--------------------------------------------------------
1. Dans la classe `User`, écrivez une méthode publique `changePassword`, avec un mot de passe en paramètre, qui effectue les étapes du fichier `changepassword.php` relatives à la BDD, c'est-à-dire :
- faire une requête vers la BDD pour mettre à jour le mot de passe de l'utilisateur `$this` avec celui passé en paramètre
- déclenche une `Exception` si la requête échoue
- mettre à jour l'attribut du mot de passe de la classe avec le nouveau mot de passe sinon
2. Modifiez le fichier `changepassword.php` en remplaçant tout ce qui concerne les requêtes vers la BDD par :
- la création d'un objet `User` à partir de son login
- l'utilisation de la méthode `changePassword` pour modifier le mot de passe de l'utilisateur dans la BDD.
> **Note** : "Try-catchez" toutes les exceptions pouvant être déclenchées par l'appel à la méthode `changePassword()`.
Exercice 7 : Passage en POO - Suppression d'un utilisateur
----------------------------------------------------------
1. Dans la classe `User`, écrivez une méthode publique `delete` qui effectue les étapes du fichier `deleteuser.php` relatives à la BDD, c'est-à-dire :
- faire une requête vers la BDD pour supprimer l'utilisateur `$this`
- déclenche une `Exception` si la requête échoue
2. Modifiez le fichier `deleteuser.php` en remplaçant tout ce qui concerne les requêtes vers la BDD par :
- la création d'un objet `User` à partir de son login
- l'utilisation de la méthode `delete` pour supprimer l'utilisateur de la BDD.
> **Note** : "Try-catchez" toutes les exceptions pouvant être déclenchées par l'appel à la méthode `delete()`.
Pour les plus rapides
---------------------
1. Créez une classe `UserException` qui hérite de la classe PHP `Exception` et utilisez-la pour les exceptions déclenchées par les méthodes de la classe `User`. Adaptez en conséquences les `try...catch` des autres fichiers.
2. Modifier l'architecture de votre application pour mettre les fichiers contrôleurs et vues dans des répertoires `controlers` et `views` au même niveau que `models`.
3. Utilisez [Bootstrap](https://getbootstrap.com) pour mettre en forme vos différentes pages.
<?php
session_start();
if ( !isset($_SESSION['user']) )
{
header('Location: signin.php');
exit();
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Account</title>
</head>
<body>
<p>
Hello <?= $_SESSION['user']; ?> !<br>
Welcome on your account.
</p>
<p><a href="signout.php">Sign out</a></p>
</body>
</html>
<?php
/******************************************************************************
* Initialisation.
*/
session_start();
unset($_SESSION['message']);
/******************************************************************************
* Traitement des données de la requête
*/
// 1. On vérifie que la méthode HTTP utilisée est bien POST
if ( $_SERVER['REQUEST_METHOD'] != 'POST' )
{
header('Location: signin.php');
exit();
}
// 2. On vérifie que les données attendues existent
if ( !isset($_POST['login'],$_POST['password']) )
{
header('Location: signin.php');
exit();
}
// 3. On sécurise les données reçues
$login = htmlentities($_POST['login']);
$password = htmlentities($_POST['password']);
/******************************************************************************
* Initialisation de l'accès à la BDD
*/
require_once('bdd.php');
/******************************************************************************
* Authentification
*/
// 1. On vérifie que le login existe dans la BDD
if ( !array_key_exists($login, $users) )
{
$_SESSION['message'] = "Wrong login.";
header('Location: signin.php');
exit();
}
// 2. On vérifie que le mot de passe associé au login est correct
if ( $users[$login] !== $password )
{
$_SESSION['message'] = "Wrong password.";
header('Location: signin.php');
exit();
}
// 3. On sauvegarde le login dans la session
$_SESSION['user'] = $login;
// 4. On sollicite une redirection vers la page du compte
header('Location: account.php');
exit();
<?php
// Ce tableau associe un nom d'utilisateur à un mot de passe :
// user => password
$users = [
'a' => 'a',
'adrien' => 'adrien',
'gabriel' => 'gabriel',
'gil' => 'gil',
];
<?php
session_start();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Signin</title>
</head>
<body>
<h1>Signin</h1>
<form action="authenticate.php" method="post">
<label for="login">Login</label> <input type="text" id="login" name="login" required autofocus>
<label for="password">Password</label> <input type="password" id="password" name="password" required>
<input type="submit" value="Signin">
</form>
<?php if ( isset($_SESSION['message']) && !empty($_SESSION['message']) ) { ?>
<section>
<p><?= $_SESSION['message']; ?></p>
</section>
<?php } ?>
</body>
</html>
<?php
session_start();
session_destroy(); // ou unset($_SESSION['user']);
header('Location: signin.php');
<?php
require_once('bdd.php');
class MyPDO
{
private static ?PDO $_pdo = null;
private function __construct() {}
public static function pdo() : PDO
{
global $SQL_DSN;
if ( self::$_pdo == null )
self::$_pdo = new PDO($SQL_DSN);
return self::$_pdo;
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment