Skip to content
Snippets Groups Projects
Commit 24c2c7a9 authored by AMOCA OKKES's avatar AMOCA OKKES
Browse files

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

parents fb9a85ed ac0bc941
Branches
No related merge requests found
Laravel
=======
**Préférez une installation sur votre ordinateur... si vous disposez d'un OS digne de ce nom ;).**
Installation de composer sur votre ordi personnel
-------------------------------------------------
```
$ sudo apt install composer
```
Installation de Laravel
-----------------------
**Attention : ce qui suit est valable sur votre ordinateur personnel ET SUR WEBETU UNIQUEMENT.**
1. Initialisation d'un projet `[NOM_DU_PROJET]` :
```
$ composer create-project --prefer-dist laravel/laravel [NOM_DU_PROJET]
```
2. Lancement d'un serveur local :
```
$ cd [NOM_DU_PROJET]
$ php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
```
Si tout s'est bien passé, votre navigateur affiche une page blanche avec le contenu suivant avec l'URL `http://127.0.0.1:8000` :
```
Laravel
|---------------|-------------------|
| Documentation | Laracasts |
|---------------|-------------------|
| Laravel News | Vibrant Ecosystem |
|---------------|-------------------|
```
TP5.md 0 → 100644
TP5 - Prise en main de Laravel
==============================
Objectif
--------
Intégrer l'application d'authentification au framework Laravel.
Vous pouvez vous baser au choix :
- sur vos propres sources résultant du TP4
- sur la proposition du répertoire [correction/TP4](correction/TP4)
Notez que le but de ce TP est d'obtenir une application fonctionnelle **mais qui ne respectera pas encore le découpage MVC**.
Les TPs suivants permettront de séparer progressivement les parties Modèle, Vue et Contrôleur en utilisant à bon escient les fonctionnalités offertes par Laravel.
Exercice 1 : Installation
-------------------------
Suivez les indications données dans [LARAVEL-installation.md](LARAVEL-Installation.md).
**Attention : `composer` n'est installé que sur webetu, pas sur troglo.**
Exercice 2 : Préparation des vues
---------------------------------
1. Copiez les fichiers suivants du TP4 dans `resources/views/` :
- `account.php`
- `adduser.php`
- `authenticate.php`
- `changepassword.php`
- `deleteuser.php`
- `formpassword.php`
- `signin.php`
- `signout.php`
- `signup.php`
1. Dans `routes/web.php` :
- Écrivez les routes GET et POST pour les fichiers ci-dessus (ne pas utiliser `Route::view`)
- Faites en sorte qu'une requête vers la racine du site propose la vue `signin.php`
- Testez toutes les routes GET. Regardez ce qu'il se passe lorsqu'on demande une route qui n'a pas été prévue dans `routes/web.php`
1. Dans chaque fichier, remplacez toutes les références à des fichiers PHP par des références à des routes.
1. Dans le fichier `app/Http/Kernel.php`, commenter les lignes qui font référence au middleware `VerifyCsrfToken`.
Exercice 3 : Modèle MyUser et PDO
---------------------------------
1. Copiez le fichier de BDD sqlite `tp4.db` du TP4 dans `database/tp5.db`.
1. Dans le fichier `.env`, modifiez les champs `DB_CONNECTION` et `DB_DATABASE` avec les informations de l'ancien fichier `bdd.php` et en suivant [cette documentation](https://laravel.com/docs/8.x/database).
1. Copiez le fichier `models/User.php` du TP4 dans le répertoire `app/Models` de votre application et renommez-le `MyUser.php`. **Attention, n'écrasez pas le fichier `User.php` existant déjà dans ce répertoire.**
1. Dans `MyUser.php` :
- déclarez le namespace `App\Models`
- remplacez le nom de la classe par `MyUser`
- remplacer les `User::USER_TABLE` par `MyUser::USER_TABLE`
- remplacer tous les `MyPDO::pdo()` par `DB::connection()->getPdo()`
- ajouter en entête les deux `use` suivants :
```php
use Illuminate\Support\Facades\DB;
use PDO;
```
1. Dans chacun des fichiers `adduser.php`, `authenticate.php`, `changepassword.php`, `deleteuser.php` et `signout.php` :
- remplacer les `require_once('models/User');` par des `use App\Models\MyUser;`
- remplacer les `new User` par des `new MyUser`
**À ce stade, l'application devrait être entièrement fonctionnelle. Solutionner les problèmes avant de passer à la suite.**
> Note : il est important d'avoir des `exit()` après chaque `header("Location: xxx")`... même si c'est la dernière instruction du fichier.
Exercice 4 : Le grand nettoyage
-------------------------------
1. Supprimer toutes les vérifications de `REQUEST_METHOD` de tous vos fichiers : c'est maintenant le routage qui le gère.
1. Supprimer tous les `session_start()` de tous vos fichiers.
1. Dans `routes/web.php`, mettre toutes les routes dans un groupe. Dans la fonction qui contient les routes de ce groupe, ajouter en première instruction un `session_start()`.
1. Dans `routes/web.php`, remplacer l'appel à la vue `signout` par le code du fichier `signout.php` et remplacer l'appel à `header()` par un appel à la méthode `redirect()` de Laravel. Supprimer `signout.php`.
1. Dans `routes/web.php`, placer les routes `changepassword`, `deleteuser`, `formpassword`, `account` et `signout` dans un groupe préfixé par `admin`. Ajouter `admin/` à ces routes dans tous les `header()` de tous vos fichiers de vues.
1. Ajouter au début de la fonction du groupe `admin` la vérification de l'existence de la variable de session `user`. Si elle n'existe pas, faire une redirection vers `signin` en utilisant `redirect` de Laravel.
**Vérifier que tout fonctionne.**
<?php
session_start();
if ( empty($_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>
<ul>
<li><a href="formpassword.php">Change password.</a></li>
<li><a href="deleteuser.php">Delete my account.</a></li>
</ul>
<p><a href="signout.php">Sign out</a></p>
<?php if ( !empty($_SESSION['message']) ) { ?>
<section>
<p><?= $_SESSION['message'] ?></p>
</section>
<?php } ?>
</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: signup.php');
exit();
}
// 2. On vérifie que les données attendues existent
if ( empty($_POST['login']) || empty($_POST['password']) || empty($_POST['confirm']) )
{
$_SESSION['message'] = "Some POST data are missing.";
header('Location: signup.php');
exit();
}
// 3. On sécurise les données reçues
$login = htmlspecialchars($_POST['login']);
$password = htmlspecialchars($_POST['password']);
$confirm = htmlspecialchars($_POST['confirm']);
// 4. On vérifie que les deux mots de passe correspondent
if ( $password !== $confirm )
{
$_SESSION['message'] = "The two passwords differ.";
header('Location: signup.php');
exit();
}
/******************************************************************************
* Chargement du model
*/
require_once('models/User.php');
/******************************************************************************
* Ajout de l'utilisateur
*/
// 1. On crée l'utilisateur avec les identifiants passés en POST
$user = new User($login,$password);
// 2. On crée l'utilisateur dans la BDD
try {
$user->create();
}
catch (PDOException $e) {
// Si erreur lors de la création de l'objet PDO
// (déclenchée par MyPDO::pdo())
$_SESSION['message'] = $e->getMessage();
header('Location: signup.php');
exit();
}
catch (Exception $e) {
// Si erreur durant l'exécution de la requête
// (déclenchée par le throw de $user->create())
$_SESSION['message'] = $e->getMessage();
header('Location: signup.php');
exit();
}
// 3. On indique que le compte a bien été créé
$_SESSION['message'] = "Account created! Now, signin.";
// 4. On sollicite une redirection vers la page d'accueil
header('Location: signin.php');
exit();
<?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 ( empty($_POST['login']) || empty($_POST['password']) )
{
$_SESSION['message'] = "Some POST data are missing.";
header('Location: signin.php');
exit();
}
// 3. On sécurise les données reçues
$login = htmlspecialchars($_POST['login']);
$password = htmlspecialchars($_POST['password']);
/******************************************************************************
* Chargement du model
*/
require_once('models/User.php');
/******************************************************************************
* Authentification
*/
// 1. On crée l'utilisateur avec les identifiants passés en POST
$user = new User($login,$password);
// 2. On vérifie qu'il existe dans la BDD
try {
if ( !$user->exists() )
{
$_SESSION['message'] = 'Wrong login/password.';
header('Location: signin.php');
exit();
}
}
catch (PDOException $e) {
// Si erreur lors de la création de l'objet PDO
// (déclenchée par MyPDO::pdo())
$_SESSION['message'] = $e->getMessage();
header('Location: signin.php');
exit();
}
catch (Exception $e) {
// Si erreur durant l'exécution de la requête
// (déclenchée par le throw de $user->exists())
$_SESSION['message'] = $e->getMessage();
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
/******************************************************************************
* Initialisation.
*/
session_start();
unset($_SESSION['message']);
/******************************************************************************
* Vérification de la session
*/
// 1. On vérifie que l'utilisateur est connecté
if ( empty($_SESSION['user']) )
{
header('Location: signin.php');
exit();
}
// 2. On récupère le login dans une variable
$login = $_SESSION['user'];
/******************************************************************************
* 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: formpassword.php');
exit();
}
// 2. On vérifie que les données attendues existent
if ( empty($_POST['newpassword']) || empty($_POST['confirmpassword']) )
{
$_SESSION['message'] = "Some POST data are missing.";
header('Location: formpassword.php');
exit();
}
// 3. On sécurise les données reçues
$newpassword = htmlspecialchars($_POST['newpassword']);
$confirmpassword = htmlspecialchars($_POST['confirmpassword']);
// 4. On s'assure que les 2 mots de passes sont identiques
if ( $newpassword != $confirmpassword )
{
$_SESSION['message'] = "Error: passwords are different.";
header('Location: formpassword.php');
exit();
}
/******************************************************************************
* Chargement du model
*/
require_once('models/User.php');
/******************************************************************************
* Changement du mot de passe
*/
// 1. On crée l'utilisateur avec les identifiants passés en POST
$user = new User($login);
// 2. On change le mot de passe de l'utilisateur
try {
$user->changePassword($newpassword);
}
catch (PDOException $e) {
// Si erreur lors de la création de l'objet PDO
// (déclenchée par MyPDO::pdo())
$_SESSION['message'] = $e->getMessage();
header('Location: formpassword.php');
exit();
}
catch (Exception $e) {
// Si erreur durant l'exécution de la requête
// (déclenchée par le throw de $user->changePassword())
$_SESSION['message'] = $e->getMessage();
header('Location: formpassword.php');
exit();
}
// 3. On indique que le mot de passe a bien été modifié
$_SESSION['message'] = "Password successfully updated.";
// 4. On sollicite une redirection vers la page du compte
header('Location: account.php');
exit();
<?php
/******************************************************************************
* Initialisation.
*/
session_start();
unset($_SESSION['message']);
/******************************************************************************
* Vérification de la session
*/
// 1. On vérifie que l'utilisateur est connecté
if ( empty($_SESSION['user']) )
{
header('Location: signin.php');
exit();
}
// 2. On récupère le login dans une variable
$login = $_SESSION['user'];
/******************************************************************************
* Chargement du model
*/
require_once('models/User.php');
/******************************************************************************
* Suppression de l'utilisateur
*/
// 1. On crée l'utilisateur avec les identifiants passés en POST
$user = new User($login);
// 2. On détruit l'utilisateur dans la BDD
try {
$user->delete();
}
catch (PDOException $e) {
// Si erreur lors de la création de l'objet PDO
// (déclenchée par MyPDO::pdo())
$_SESSION['message'] = $e->getMessage();
header('Location: account.php');
exit();
}
catch (Exception $e) {
// Si erreur durant l'exécution de la requête
// (déclenchée par le throw de $user->create())
$_SESSION['message'] = $e->getMessage();
header('Location: account.php');
exit();
}
// 3. On détruit la session
session_destroy();
// 4. On crée une nouvelle session
session_start();
// 5. On indique que le compte a bien été supprimé
$_SESSION['message'] = "Account successfully deleted.";
// 6. On sollicite une redirection vers la page d'accueil
header('Location: signin.php');
exit();
<?php
session_start();
if ( empty($_SESSION['user']) )
{
header('Location: signin.php');
exit();
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Change password</title>
</head>
<body>
<h1>Change password</h1>
<form action="changepassword.php" method="post">
<label for="newpassword">New password</label> <input type="password" id="newpassword" name="newpassword" required>
<label for="confirmpassword">Confirm password</label><input type="password" id="confirmpassword" name="confirmpassword" required>
<input type="submit" value="Change my password">
</form>
<p>
Go back to <a href="account.php">Home</a>.
</p>
<?php if ( !empty($_SESSION['message']) ) { ?>
<section>
<p><?= $_SESSION['message'] ?></p>
</section>
<?php } ?>
</body>
</html>
<?php
require_once("MyPDO.php");
class User
{
private string $_login;
private ?string $_password;
private const USER_TABLE = "Users";
public function __construct( string $login, string $password = null )
{
$this->setLogin($login);
$this->setPassword($password);
}
public function login() : string
{
return $this->_login;
}
public function setLogin( string $login ) : void
{
$this->_login = $login;
}
public function password() : string
{
return $this->_password;
}
public function setPassword( ?string $password ) : void
{
$this->_password = $password;
}
public function exists() : bool
{
// 1. On prépare la requête $request
$request = MyPDO::pdo()->prepare('SELECT password FROM '.self::USER_TABLE.' WHERE login = :login');
// 2. On assigne $login au paramêtre :login
$ok = $request->bindValue( ":login", $this->_login, PDO::PARAM_STR );
// 3. On exécute la requête $request
$ok &= $request->execute();
if (!$ok)
throw new Exception("Error: user access in DB failed.");
// 4. On vérifie que l'utilisateur a été trouvé et que son mot de passe
// correspond à celui de l'attribut $this->_password
$user = $request->fetch(PDO::FETCH_ASSOC);
return $user && password_verify($this->_password,$user['password']);
}
public function create() : void
{
$request = MyPDO::pdo()->prepare('INSERT INTO '.self::USER_TABLE.'(login,password) VALUES (:login,:password)');
$ok = $request->bindValue( ":login", $this->_login, PDO::PARAM_STR );
$ok &= $request->bindValue( ":password", password_hash($this->_password,PASSWORD_DEFAULT), PDO::PARAM_STR );
$ok &= $request->execute();
if ( !$ok )
throw new Exception("Error: user creation in DB failed.");
}
public function changePassword( string $newpassword ) : void
{
$request = MyPDO::pdo()->prepare('UPDATE '.self::USER_TABLE.' SET password = :password WHERE login = :login');
$ok = $request->bindValue(':login', $this->_login, PDO::PARAM_STR);
$ok &= $request->bindValue(':password', password_hash($newpassword,PASSWORD_DEFAULT), PDO::PARAM_STR);
$ok &= $request->execute();
if ( !$ok )
throw new Exception("Error: password updating failed.");
$this->setPassword($newpassword);
}
public function delete() : void
{
$request = MyPDO::pdo()->prepare('DELETE FROM '.self::USER_TABLE.' WHERE login = :login');
$ok = $request->bindValue(':login', $this->_login, PDO::PARAM_STR);
$ok &= $request->execute();
if ( !$ok )
throw new Exception("Error while deleting your account.");
}
}
<?php
// Nom du fichier du fichier de BDD SQLite sur le serveur
$sqliteFile = $_SERVER['DOCUMENT_ROOT'].'/models/tp4.db';
// Exception si le fichier n'existe pas
if (!file_exists($sqliteFile))
throw new PDOException("DB file '".$sqliteFile."' doesn't exist");
// Variable contenant le DSN de la BDD SQLite
$SQL_DSN = 'sqlite:'.$sqliteFile;
File added
<?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>
<p>
If you don't have an account, <a href="signup.php">signup</a> first.
</p>
<?php if ( !empty($_SESSION['message']) ) { ?>
<section>
<p><?= $_SESSION['message'] ?></p>
</section>
<?php } ?>
</body>
</html>
<?php
session_start();
session_destroy();
header('Location: signin.php');
<?php
session_start();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Signup</title>
</head>
<body>
<h1>Signup</h1>
<form action="adduser.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>
<label for="confirm">Confirm password</label><input type="password" id="confirm" name="confirm" required>
<input type="submit" value="Signup">
</form>
<p>
If you already have an account, <a href="signin.php">signin</a>.
</p>
<?php if ( !empty($_SESSION['message']) ) { ?>
<section>
<p><?= $_SESSION['message'] ?></p>
</section>
<?php } ?>
</body>
</html>
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