Présentation de l’authentification sur symfony https://openclassrooms.com/courses/developpez-votre-site-web-avec-le-framework-symfony2/securite-et-gestion-des-utilisateurs
Dans la structure security (configuration du security manager) :
reprendre les tp2/3/4
créer un contrôleur src/Controller/IndexController avec une route /
<?php
namespace App\Controller;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
class IndexController extends AbstractController
{
/**
* @Route("/", name="index_index")
*/
public function index(Request $request)
{
// if(! is_null($this->getUser())){
// echo "<br>";
// echo " id: ".$this->getUser()->getId();
// echo " roles : ";
// print_r($this->getUser()->getRoles());
// die();
// }
if($this->isGranted('ROLE_ADMIN')) {
return $this->redirectToRoute('admin_produit_index');
// return $this->render('admin/produit/showProduits.html.twig');
}
if($this->isGranted('ROLE_CLIENT')) {
return $this->redirectToRoute('client_panierSession_index');
// return $this->render('client/boutique/produit.html.twig');
}
return $this->render('accueil.html.twig');
}
}
<?php
namespace App\Controller\Client;
use App\Entity\Produit;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class PanierSessionController extends AbstractController
{
/**
* @Route("/client", name="client_panierSession_index", methods={"GET"})
* @Route("/client/produits/show", name="client_panierSession_showProduits", methods={"GET"})
*/
public function showPanierSessionProduits(Request $request)
{
$produits = $this->getDoctrine()->getRepository(Produit::class)->findBy([], ['typeProduit' => 'ASC', 'stock' => 'ASC']);
return $this->render('client/boutique/panier_produit.html.twig', ['produits' => $produits]);
}
}
Il faut suivre la Documentation : https://symfony.com/doc/master/security.html
php bin/console make:user
The name of the security user class (e.g. User) [User]:
> User
Do you want to store user data in the database (via Doctrine)? (yes/no) [yes]:
> yes
Enter a property name that will be the unique "display" name for the user (e.g.
email, username, uuid [email]
>
username
Does this app need to hash/check user passwords? (yes/no) [yes]:
> yes
created: src/Entity/User.php
created: src/Repository/UserRepository.php
updated: src/Entity/User.php
updated: config/packages/security.yaml
__toString
// ********************************
/**
* @ORM\Column(type="string", length=60, unique=true)
*/
private $email;
/**
* @ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* @ORM\Column(type="string", nullable=true)
*/
private $nom = '';
/**
* @ORM\Column(type="string", nullable=true)
*/
private $ville = '';
/**
* @ORM\Column(type="string", nullable=true)
*/
private $codePostal = '';
/**
* @ORM\Column(type="string", nullable=true)
*/
private $adresse = '';
/**
* @ORM\Column(type="string", nullable=true)
*/
private $tokenMail = '';
public function __toString()
{
// TODO: Implement __toString() method.
return "username : ".$this->getUsername()." role: ".$this->getRoles()[0]." mdp:".$this->getPassword();
}
public function __construct()
{
$this->isActive = true;
}
php bin/console make:entity --regenerate
php bin/console doctrine:schema:update --force
use App\Entity\User;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
.....
private $passwordEncoder;
public function __construct(UserPasswordEncoderInterface $passwordEncoder)
{
$this->passwordEncoder = $passwordEncoder;
}
// appeler la méthode loadUsers dans la méthode load
public function loadUsers(ObjectManager $manager)
{
echo " \n\nles utilisateurs : \n";
$admin = new User();
$password = $this->passwordEncoder->encodePassword($admin, 'admin');
$admin->setPassword($password);
$admin->setRoles(['ROLE_ADMIN'])
->setUsername('admin')->setEmail('admin@example.com')->setIsActive('1');
$manager->persist($admin);
echo $admin."\n";
$client = new User();
$password = $this->passwordEncoder->encodePassword($client, 'client');
$client->setPassword($password);
$client->setRoles(['ROLE_CLIENT'])->setUsername('client')
->setEmail('client@example.com')->setIsActive('1');
$manager->persist($client);
echo $client."\n";
$client2 = new User();
$password = $this->passwordEncoder->encodePassword($client, 'client2');
$client2->setPassword($password);
$client2->setRoles(['ROLE_CLIENT'])->setUsername('client2')
->setEmail('client2@example.com')->setIsActive('1');
$manager->persist($client2);
echo $client2."\n";
$manager->flush();
}
php bin/console doctrine:fixtures:load
bin/console doctrine:query:sql "select * from user;"
bin/console security:encode-password admin
Dans symfony, un assistant permet de gagner beaucoup de temps si on désire une authentification basique
Suivre la documentation symfony https://symfony.com/doc/current/security/form_login_setup.html
php bin/console make:auth
What style of authentication do you want? [Empty authenticator]:
[0] Empty authenticator
[1] Login form authenticator
> 1
The class name of the authenticator to create (e.g. AppCustomAuthenticator):
> LoginFormAuthenticator
...
created: src/Security/LoginFormAuthenticator.php
=> permet de voir les différentes méthodes lors de l’authentification
created: src/Controller/SecurityController.php
=> permet de voir les routes pour s’authentifier et se déconnecter
created: templates/security/login.html.twig
=> formulaire pour se connecter (très facile à modifier, pour franciser le formulaire, changer le style ) templates/security/login.html.twig
{% extends 'layout_home.html.twig' %}
updated: config/packages/security.yaml
tester
il faut modifier le fichier src/Security/LoginFormAuthenticator.php
et ajouter :
return new RedirectResponse($this->urlGenerator->generate('index_index'));
Le plus important : sécuriser les routes et les classes
https://symfony.com/doc/current/security.html#firewalls-authentication
security:
# .......
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
#- { path: ^/, roles: [ROLE_USER, ROLE_CLIENT] }
- { path: ^/client, roles: ROLE_CLIENT }
- { path: ^/admin, roles: ROLE_ADMIN }
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
/**
* devant la Class AdminController
* @IsGranted("ROLE_ADMIN")
*/
Attention aux majuscules et minuscules des mots clés (nom des objets et des méthodes) !!
config/packages/security.yml
les access_control
il est possible de mettre des restrictions directement dans le code https://symfony.com/doc/master/security.html#securing-controllers-and-other-code
{% if is_granted('ROLE_ADMIN') %}
<a href="...">Delete</a>
{% endif %}
{% if is_granted('IS_AUTHENTICATED_FULLY') %}
<p>Email: {{ app.user.email }}</p>
{% endif %}
{% if is_granted('IS_AUTHENTICATED_FULLY') %}
<p> Bonjour Username: {{ app.user.username }}</p> {% if is_granted('ROLE_ADMIN') %} (role : Admin ) <br>{% endif %}
{% if is_granted('ROLE_USER') %} (role : User ) <br>{% endif %}
<a href="{{ path('app_logout') }}"> deconnexion</a><br>
{% else %}
<a href="{{ path('app_login') }}"> se connecter</a><br>
{% endif %}
voir exemple dans IndexController.php pour récupérer l’identifiant de l’utilisateur connecté https://symfony.com/doc/current/security.html#a-fetching-the-user-object
if(! is_null($this->getUser())){
echo "<br>";
echo " id: ".$this->getUser()->getId();
echo " roles : ";
print_r($this->getUser()->getRoles());
die();
}
http://symfony.com/doc/current/security/access_control.html
dans le bloc security, ajouter au ROLE_USER les droits de ROLE_ADMIN
security:
#.....
role_hierarchy:
ROLE_USER: ROLE_ADMIN
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
https://symfony.com/doc/4.2/doctrine/registration_form.html
utiliser la documentation ci-dessous pour configurer le message d’erreur (très facile)
https://symfony.com/doc/current/security/access_denied_handler.html
https://www.youtube.com/watch?v=_GjHWa9hQic&feature=youtu.be
/logout
(ancienne version)fichier config/routes.yaml , ne pas oublier
logout:
path: /logout
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
/**
* devant la Class AdminController
* @Security("has_role('ROLE_ADMIN')")
*/