Sécurisation de vos applications web
à l’aide du composant Security de Symfony
28 août 2018
https://vria.eu
contact@vria.eu
https://twitter.com/RiaVlad
RIABCHENKO Vladyslav
5+ ans full stack web-développeur
Certifié Symfony
Architecte technique à Webnet
Symfony 3
1. Symfony
2. Authentification artisanale
3. Firewall
4. Token anonyme
5. User provider
6. Authentication provider
7. HTTP Basic
8. Formulaire de connexion
Plan
Symfony 4
Authentification est un processus permettant à l’application de s’assurer que la requête
a été faite par un utilisateur légitime.
C’est une confirmation de son identité grâce à des identifiants.
Identification est une sélection d’utilisateur grâce à son identifiant.
Autorisation est une vérification des droits d’accès d’un utilisateur sur une ressource en
se basant sur une politique d’accès.
Auth simple 5
Authentifier chaque requête à l’application à l’aide d’un identifiant et d’un
mot de passe.Tâche 1
Front controller
Token
public/index.php reçoit toutes les requêtes client quelque soit le
path et les paramètres
HttpFoundation
Composant de Symfony qui fournit la couche orientée-objet pour
HTTP : Request, Response, Session, etc.
Conserve des données sur l’utilisateur :
• Objet d’utilisateur
• Username
• Credentials
• Roles
• Authentifié ou pas
SymfonyComponentSecurityCoreAuthenticationToken
6
Security listeners
Token Conserve des données sur l’utilisateur
+ getUser()
+ getUsername()
+ getCredentials()
+ isAuthenticated()
+ getRoles()
TokenInterface
+ getProviderKey()
UsernamePasswordToken
+ getSecret()
AnonymousToken
Listeners qui extraient les identifiants et les vérifient.
Ils créent ensuite un Token puis le stockent dans le Token storage.
Token storage Objet/service qui contient un Token
Auth simple
7
// public/index.php
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorage;
use SymfonyComponentHttpFoundationResponse;
$request = Request::createFromGlobals(); // HTTP request
$tokenStorage = new TokenStorage(); // Service that stores user token
// Call security listener on every request.
$securityListener = new AppSecuritySecurityListener($tokenStorage);
$securityListener->onRequest($request);
// Any code you can imagine to generate a response.
// You can deny access if no token were set.
$token = $tokenStorage->getToken();
$response = new Response(
'Request uri: '.$request->getRequestUri().'<br>'
.'Token: '.(is_object($token) ? get_class($token) : gettype($token)).'<br>'
.'Username: '.($token ? $token->getUsername(): 'NULL')
);
$response->send(); // Send response
Auth simple
8
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorageInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken;
class SecurityListener
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function onRequest(Request $request)
{
$user = $request->query->get('auth_user');
$password = $request->query->get('auth_pw');
if ($user === 'vlad' && $password === 'pass') {
// Credentials are valid.
// Create a token with user object, credentials, provider key and roles
$token = new UsernamePasswordToken($user, $password, 'main', ['ROLE_USER']);
// Save it to token storage
$this->tokenStorage->setToken($token);
}
}
}
Auth simple
Firewall 9
Centraliser l’authentification dans un firewall afin de pouvoir utiliser
plusieurs systèmes d’authentification.Tâche 2
HttpKernel
Le composant de Symfony qui fournit un processus structuré pour
convertir Request en Response en utilisant EventDispatcher.
EventDispatcher
Le composant de Symfony qui permet aux composants de
communiquer entre eux à l’aide d’événements.
Request ResponseResolve controller Execute controller
EXCEPTIONEvent Dispatcher
// public/index.php
use SymfonyComponentEventDispatcherEventDispatcher;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpKernelHttpKernel;
use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorage;
$request = Request::createFromGlobals(); // HTTP request.
$tokenStorage = new TokenStorage(); // Service that stores user token.
$dispatcher = new EventDispatcher();
// Controller creates a response to send to the user.
$controller = new AppController($request, $tokenStorage);
$controllerResolver = new AppControllerResolver([$controller, 'defaultAction']);
// kernel is in charge of converting a Request into a Response by using the event dispatcher.
$kernel = new HttpKernel($dispatcher, $controllerResolver);
// We will add security listeners to dispatcher in few minutes.
$response = $kernel->handle($request);
$response->send();
10Firewall
Le Front controller crée $kernel et lui demande de traiter la requête.
11
Kernel demande à ControllerResolver de renvoyer le contrôleur en fonction de la
requête. C’est l’emplacement idéal pour la logique de Routing.
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpKernelControllerControllerResolverInterface;
class ControllerResolver implements ControllerResolverInterface
{
/** @var callable */
private $default;
public function __construct(callable $default)
{
$this->default = $default;
}
public function getController(Request $request)
{
return $this->default;
}
}
Firewall
12
class Controller
{
/** @var Request */
private $request;
/** @var TokenStorageInterface */
private $tokenStorage;
public function defaultAction()
{
$token = $this->tokenStorage->getToken();
return new Response(
'Request uri: '.$this->request->getRequestUri().'<br>'
.'Token: '.(is_object($token) ? get_class($token) : gettype($token)).'<br>'
.'Username: '.($token ? $token->getUsername(): 'NULL')
);
}
}
La méthode Controller::defaultAction est un contrôleur qui sera exécuté par Kernel.
Firewall
SymfonyComponentSecurityHttp
13
- map: array
+ getListeners(Request $request)
Firewall
- map: FirewallMap
+ onKernelRequest(GetResponseEvent $event)
FirewallMap
RequestMatcher
- path: string
=>
][
Le firewall est un listener de l’événement
REQUEST.
Il permet d’implémenter des stratégies
d’authentification en fonction de la
requête.
FirewallMap renvoie les listeners
configurés pour le requête spécifique.
ListenerInterface
+ handle(GetResponseEvent $event) , …
Firewall
14
RequestMatcher
- path = ^/back
- ips = [192.0.0.4]
=>
][ BasicAuthenticationListener
RequestMatcher
- path: ^/customer
=>
][ ContextListener
,
SimpleFormAuthenticationListener
RequestMatcher =>
][AnonymousAuthenticationListener
Utiliser l’authentification HTTP basic pour toutes les requêtes qui commencent par /back
Authentifier les requêtes qui commencent par /customer à l’aide d’un formulaire classique
Authentifier toutes les autres requêtes comme anonymes
Firewall
15
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewall;
use SymfonyComponentSecurityHttpFirewallMap;
// ...
// Create main security listener that handles authentication.
$securityListener = new AppSecurityMainSecurityListener($tokenStorage);
// Create firewall map and add main security listener under URLs starting with "/main".
$firewallMap = new FirewallMap();
$firewallMap->add(new RequestMatcher('^/main'), [$securityListener]);
// Create firewall and add it to dispatcher.
$firewall = new Firewall($firewallMap, $dispatcher);
$dispatcher->addSubscriber($firewall);
// ...
Firewall attends l’événement REQUEST pour exécuter MainSecurityListener si le path de
la requête commence par /main.
Firewall
16
use SymfonyComponentHttpKernelEventGetResponseEvent;
use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorageInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken;
use SymfonyComponentSecurityHttpFirewallListenerInterface;
class MainSecurityListener implements ListenerInterface
{
/** @var TokenStorageInterface */
private $tokenStorage;
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
$user = $request->query->get('auth_user');
$password = $request->query->get('auth_pw');
if ($user === 'vlad' && $password === 'pass') {
$token = new UsernamePasswordToken($user, $password, 'main', ['ROLE_USER']);
$this->tokenStorage->setToken($token);
}
}
}
MainSecurityListener implémente désormais ListenerInterface.
Firewall
App
SymfonyComponentSecurityHttpFirewall
anon. 17
Permettre aux utilisateurs de s’authentifier comme des anonymes.Tâche 3
RequestMatcher
- path = ^/main =>
][
MainSecurityListener
AnonymousAuthenticationListener
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewallMap;
use SymfonyComponentSecurityHttpFirewallAnonymousAuthenticationListener;
// ...
// Create a security listener that adds anonymous token if none is already present.
$anonListener = new AnonymousAuthenticationListener($tokenStorage, 'secret');
// Create firewall map and add main security listener under URLs starting with "/main".
$firewallMap = new FirewallMap();
$firewallMap->add(new RequestMatcher('^/main'), [$securityListener, $anonListener]);
User provider 18
Abstraire le moyen de récupération des utilisateurs et déplacer cette logique
en dehors des security listeners.Tâche 4
SymfonyComponentSecurityCoreUser
UserProviderInterface
+ loadUserByUsername($username): UserInterface
+ refreshUser(UserInterface $user)
+ supportsClass($class)
Security Listener
- userProvider
+ loadUserByUsername($username):User
UserInterface
+ getUsername()
+ getRoles()
+ getPassword()
+ getSalt()
+ eraseCredentials()
+ isEnabled()
UserInMemoryUserProvider
19
use SymfonyComponentHttpKernelEventGetResponseEvent;
use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken;
use SymfonyComponentSecurityCoreExceptionUsernameNotFoundException;
use SymfonyComponentSecurityCoreUserUserProviderInterface;
use SymfonyComponentSecurityHttpFirewallListenerInterface;
class MainSecurityListener implements ListenerInterface
{
/** @var UserProviderInterface */
private $userProvider;
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
$username = $request->query->get('auth_user');
$password = $request->query->get('auth_pw');
try {
$user = $this->userProvider->loadUserByUsername($username);
if ($user->getPassword() === $password) {
$token = new UsernamePasswordToken($user, $password, 'main', $user->getRoles());
$this->tokenStorage->setToken($token);
}
} catch (UsernameNotFoundException $e) {
}
}
}
User provider
20
// public/index.php
use SymfonyComponentEventDispatcherEventDispatcher;
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewallMap;
use SymfonyComponentSecurityHttpFirewall;
use SymfonyComponentSecurityCoreUserInMemoryUserProvider;
// ...
// Create user provider that will be used by authentication listener.
$mainUserProvider = new InMemoryUserProvider([
'vlad' => ['password' => 'pass', 'roles' => ['ROLE_USER’]],
]);
// Create main security listener that handles authentication.
$mainSecurityListener = new AppSecurityMainSecurityListener($tokenStorage, $mainUserProvider);
// Create firewall map and add main security listener under URLs starting with "/main".
$firewallMap = new FirewallMap();
$firewallMap->add(new RequestMatcher('^/main'), [$mainSecurityListener, $anonListener]);
// ...
User provider
Création d’un user provider pour main security listener.
App
21Auth provider
Ajouter l’encodage du mot de passe, n’accepter que des utilisateurs activés.
Déplacer la logique d’authentification en dehors des security listeners.Tâche 5
- tokenStorage
- authenticationManager
SymfonyComponentSecurityCoreAuthentication
AuthenticationManagerInterface
+ authenticate(TokenInterface $token)
MainSecurityListener
̶ Être rappelé par Firewall pendant l’événement
REQUEST
̶ Extraire l’identifiant et le mot de passe
̶ Créer le token non authentifié
̶ Passer le token à l’authentification manager
̶ Mettre le token authentifié dans le token storage
̶ Récupérer l’utilisateur grâce à l’identifiant et à
l’aide de user provider
̶ Vérifier le mot de passe à l’aide de password
encoder
̶ Vérifier les autres paramètres
̶ Renvoyer le token authentifié
$token->setAuthenticated(true)
créer un nouveau token
SymfonyComponentSecurityCoreAuthentication
22Auth provider
Provider
DaoAuthenticationProvider
- userProvider
- encoderFactory
- userChecker
AuthenticationManagerInterface
+ authenticate(TokenInterface $token)
SymfonyComponentSecurityCoreUser
UserProviderInterface
+ loadUserByUsername($username)
+ refreshUser(UserInterface $user)
+ supportsClass($class)
+ loadUserByUsername($username):User
InMemoryUserProvider
SymfonyComponentSecurityCoreAuthentication
23Auth provider
Provider
DaoAuthenticationProvider
- userProvider
- encoderFactory
- userChecker
SymfonyComponentSecurityCoreEncoder
EncoderFactoryInterface
+ getEncoder($user): PasswordEncoderInterface
PasswordEncoderInterface
+ encodePassword($raw, $salt)
+ isPasswordValid($encoded, $raw, $salt)
- cost: int
BCryptPasswordEncoder
- encoders: array
EncoderFactory
SymfonyComponentSecurityCoreAuthentication
24Auth provider
Provider
DaoAuthenticationProvider
AuthenticationManagerInterface
+ authenticate(TokenInterface $token)
SymfonyComponentSecurityCoreUser
UserChecker
+ checkPreAuth(UserInterface $user)
+ checkPostAuth(UserInterface $user)
UserCheckerInterface
- userProvider
- encoderFactory
- userChecker
25Auth provider
use SymfonyComponentSecurityCoreAuthenticationAuthenticationManagerInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken;
use SymfonyComponentSecurityCoreExceptionAuthenticationException;
class MainSecurityListener implements ListenerInterface
{
/** @var AuthenticationManagerInterface */
private $authenticationManager;
public function handle(GetResponseEvent $event)
{
// Extract authentication credentials.
if ($username && $credentials) {
try {
// Token is not authenticated because no role is passed.
$token = new UsernamePasswordToken($username, $credentials, 'main');
// Try to authenticate the token.
// If there is an authentication error an AuthenticationException is thrown.
$token = $this->authenticationManager->authenticate($token);
// Add authenticated token to storage.
$this->tokenStorage->setToken($token);
} catch (AuthenticationException $e) {}
}
}
}
26Auth provider
use SymfonyComponentSecurityCoreAuthenticationProviderDaoAuthenticationProvider;
use SymfonyComponentSecurityCoreEncoderBCryptPasswordEncoder;
// Create user provider that will be used by authentication listener.
$mainUserProvider = new InMemoryUserProvider([
'vlad' => [
'password' => '$2y$10$zDUW3BF4T5ZVloDZqp0SN.1Ic4DG3xfxHUDXWkkpvaP0G8qXnq', // encoded 'pass'
'roles' => ['ROLE_USER'],
'enabled' => true
]
]);
// And object that checks whether a user is non-locked, enabled, not expired, etc.
$mainUserChecker = new SymfonyComponentSecurityCoreUserUserChecker();
// A factory that specifies encoding algorithm to each user class.
$encoderFactory = new SymfonyComponentSecurityCoreEncoderEncoderFactory([
SymfonyComponentSecurityCoreUserUser::class => new BCryptPasswordEncoder(10)
]);
// Create a provider to which security listener will delegate an authentication.
$mainAuthProvider = new DaoAuthenticationProvider(
$mainUserProvider, $mainUserChecker, 'main', $encoderFactory
);
// Create main security listener that handles authentication.
$mainSecurityListener = new AppSecurityMainSecurityListener($tokenStorage, $mainAuthProvider);
27HTTP basic auth
Mettre en place l’authentification HTTP, laisser passer seulement les
utilisateurs connectés.Tâche 6
SymfonyComponentSecurityHttpFirewall
- tokenStorage
- authenticationManager
BasicAuthenticationListener
- tokenStorage
- accessDecisionManager
AccessListener
RequestMatcher
- path: ^/main
=>
Extraire l’identifiant et le mot de
passe de l'en-tête Authorization.
Créer le token, l'authentifier, le
sauvegarder dans token storage.
Lancer une exception si les
credentials ne sont pas valides. Lancer une exception si le token
n’est pas présent ou s’il ne
respecte pas les règles d’accès.
28
SymfonyComponentSecurityHttpEntryPoint
+ start(Request $request, $authException): Response
AuthenticationEntryPointInterface
- realmName: string
BasicAuthenticationEntryPoint
Lors de l'exception d’authentification (accès anonyme ou identifiants non valides) il faut
aider l’utilisateur à (re-)commencer l’authentification.
SymfonyComponentSecurityHttpFirewall
- tokenStorage
- authenticationManager
- authenticationEntryPoint
BasicAuthenticationListener
Event Dispatcher
- Kernel::EXCEPTION => [...]
- authenticationEntryPoint
ExceptionListener
HTTP basic auth
29
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpAccessMap;
use SymfonyComponentSecurityHttpFirewallMap;
use SymfonyComponentSecurityHttpFirewallBasicAuthenticationListener;
use SymfonyComponentSecurityHttpFirewallAccessListener;
use SymfonyComponentSecurityHttpEntryPointBasicAuthenticationEntryPoint;
use SymfonyComponentSecurityCoreAuthorizationAccessDecisionManager;
// Entry point helps user to authenticate.
$basicAuthenticationEntryPoint = new BasicAuthenticationEntryPoint('Secured area');
// Create HTTP basic security listener that extracts credentials from headers (RFC 7617).
$mainSecurityListener = new BasicAuthenticationListener(
$tokenStorage, $mainAuthProvider, 'main', $basicAuthenticationEntryPoint
);
// Access listener will throw an exception when no token is already present.
$accessDecisionManager = new AccessDecisionManager();
$accessMap = new AccessMap();
$accessListener = new AccessListener(
$tokenStorage, $accessDecisionManager, $accessMap, $mainAuthProvider
);
// Create firewall map and add main security listener under URLs starting with "/main".
$firewallMap = new FirewallMap();
$firewallMap->add(new RequestMatcher('^/main'), [$mainSecurityListener, $accessListener]);
// ...
HTTP basic auth
30
use SymfonyComponentSecurityHttpHttpUtils;
use SymfonyComponentSecurityCoreAuthenticationAuthenticationTrustResolver;
use SymfonyComponentSecurityCoreAuthenticationTokenAnonymousToken;
use SymfonyComponentSecurityCoreAuthenticationTokenRememberMeToken;
use SymfonyComponentHttpKernelKernelEvents;
// ...
// ExceptionListener catches authentication exception and converts them to Response instance.
// In this case it invites user to enter its credentials by returning 401 response.
$authTrustResolver = new AuthenticationTrustResolver(AnonymousToken::class, RememberMeToken::class);
$httpUtils = new HttpUtils();
$exceptionListener = new ExceptionListener(
$tokenStorage, $authTrustResolver, $httpUtils, 'main', $basicAuthenticationEntryPoint
);
$dispatcher->addListener(KernelEvents::EXCEPTION, array($exceptionListener, 'onKernelException'), 1);
// ...
HTTP basic auth
31Formulaire de connexion
Mettre en place l’authentification par le formulaire de connexion pour une
autre partie de site.Tâche 7
SymfonyComponentSecurityHttpFirewall
- tokenStorage
- userProviders
ContextListener
- tokenStorage
- accessDecisionManager
- options
- successHandler
- failureHandler
UsernamePasswordFormAuthenticationListener
RequestMatcher
- path: ^/front
=>
+ handle(GetResponseEvent $event)
+ onKernelResponse(FilterResponseEvent $event)
+ handle(GetResponseEvent $event)
Récupérer le token d’une session
lors de l’événement REQUEST.
Sauvegarder le token dans une
session lors de l’événement
RESPONSE.
Authentifier l’utilisateur
seulement quand le formulaire de
connexion est envoyé
(POST sur /front/login_check).
32Formulaire de connexion
use SymfonyComponentHttpFoundationResponse;
class Controller
{
public function loginFormAction()
{
return new Response(<<<END
<form action="/front/login_check" method="POST">
<input type="text" name="_username" placeholder="username">
<input type="password" name="_password" placeholder="password">
<input type="submit">
</form>
END
);
}
public function defaultAction()
{
$token = $this->tokenStorage->getToken();
$user = $token ? $token->getUser() : null;
// ...
}
}
Nouvelle action pour visualiser le formulaire de conexion : POST sur /front/login_check.
33Formulaire de connexion
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpKernelControllerControllerResolverInterface;
class ControllerResolver implements ControllerResolverInterface
{
/** @var callable[] */
private $routes;
/** @var callable */
private $default;
public function getController(Request $request)
{
foreach ($this->routes as $pattern => $controller) {
if (preg_match($pattern, $request->getPathInfo())) {
return $controller;
}
}
return $this->default;
}
}
La nouvelle action sera appelée quand la requête est faite sur /font/login.
34Formulaire de connexion
// public/index.php
use SymfonyComponentEventDispatcherEventDispatcher;
use SymfonyComponentHttpKernelHttpKernel;
// ...
// Controller creates a response to send to the user.
$controller = new AppController($request, $tokenStorage);
$controllerResolver = new AppControllerResolver(
['/^/front/login$/' => [$controller, 'loginFormAction']],
[$controller, 'defaultAction']
);
// Kernel is in charge of converting a Request into a Response by using the event dispatcher.
$kernel = new HttpKernel($dispatcher, $controllerResolver);
// ...
La nouvelle action sera appelée quand la requête est faite sur /font/login.
35Formulaire de connexion
// public/index.php
use SymfonyComponentSecurityHttpFirewallContextListener;
// ...
// ContextListener retrieves previously authenticated token from the session during REQUEST event.
// It also saves token during RESPONSE event.
$contextListener = new ContextListener(
$tokenStorage, [$mainUserProvider], 'front', null, $dispatcher
);
// ...
Context security listener :
36Formulaire de connexion
use SymfonyComponentSecurityHttpAuthenticationDefaultAuthenticationSuccessHandler;
use SymfonyComponentSecurityHttpAuthentication DefaultAuthenticationFailureHandler;
use SymfonyComponentSecurityHttpFirewallUsernamePasswordFormAuthenticationListener;
use SymfonyComponentSecurityHttpSessionSessionAuthenticationStrategy;
$sessionAuthenticationStrategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE);
$successHandler = new DefaultAuthenticationSuccessHandler(
$httpUtils, ['default_target_path' => '/front/success’]
);
$failureHandler = new DefaultAuthenticationFailureHandler(
$kernel, $httpUtils, ['login_path' => '/front/login’]
);
// Listens for login form being send (POST to '/front/login_check').
// It extracts credentials, creates token, authenticates it and puts it to the token storage.
$formAuthListener = new UsernamePasswordFormAuthenticationListener(
$tokenStorage,
$frontAuthProvider,
$sessionAuthenticationStrategy,
$httpUtils,
'front',
$successHandler, // Redirect user to '/front/success' if credentials are valid
$failureHandler, // Redirect user to '/front/login' if credentials are invalid
['check_path' => '/front/login_check’, 'post_only' => true] // Act only on POST to '/front/login_check'
);
37Formulaire de connexion
// public/index.php
use SymfonyComponentHttpFoundationRequestMatcher;
use SymfonyComponentSecurityHttpFirewallMap;
// ...
$firewallMap = new FirewallMap();
$firewallMap->add(new RequestMatcher('^/main'), [$mainSecurityListener, $accessListener]);
$firewallMap->add(new RequestMatcher('^/front'), [$contextListener, $formAuthListener]);
// ...
Ajout de security listeners dans le Firewall :
Merci pour votre attention
Le code de cette présentation :
https://github.com/vria/symfony-security-component-use

More Related Content

PPTX
Sécurisation de vos applications web à l’aide du composant Security de Symfony
PPTX
SOLID: the core principles of success of the Symfony web framework and of you...
PDF
Symfony As A Platform (Symfony Camp 2007)
PPTX
Speed up your developments with Symfony2
PDF
Symfony War Stories
PDF
Symfony components in the wild, PHPNW12
PDF
Desenvolvendo em php cli
PDF
Client-side Auth with Ember.js
Sécurisation de vos applications web à l’aide du composant Security de Symfony
SOLID: the core principles of success of the Symfony web framework and of you...
Symfony As A Platform (Symfony Camp 2007)
Speed up your developments with Symfony2
Symfony War Stories
Symfony components in the wild, PHPNW12
Desenvolvendo em php cli
Client-side Auth with Ember.js

What's hot (20)

PDF
Php e Cassandra
PDF
Symfony 2.0 on PHP 5.3
PDF
Php vulnerability presentation
PDF
Let's play a game with blackfire player
PDF
Symfony without the framework
PDF
TestFest - Respect\Validation 1.0
PDF
The symfony platform: Create your very own framework (PHP Quebec 2008)
PDF
Php Security
PDF
The Enterprise Wor/d/thy/Press
PDF
The state of Symfony2 - SymfonyDay 2010
PDF
Implementing OAuth with PHP
PDF
PHP 5.3 in practice
PDF
WordPress REST API hacking
PPTX
New in php 7
PDF
Symfony2 - WebExpo 2010
PDF
Elixir Paris Meetup
PDF
Symfony2 - OSIDays 2010
PDF
Dependency Injection with PHP 5.3
PDF
Dirty Secrets of the PHP SOAP Extension
PDF
Unit and Functional Testing with Symfony2
Php e Cassandra
Symfony 2.0 on PHP 5.3
Php vulnerability presentation
Let's play a game with blackfire player
Symfony without the framework
TestFest - Respect\Validation 1.0
The symfony platform: Create your very own framework (PHP Quebec 2008)
Php Security
The Enterprise Wor/d/thy/Press
The state of Symfony2 - SymfonyDay 2010
Implementing OAuth with PHP
PHP 5.3 in practice
WordPress REST API hacking
New in php 7
Symfony2 - WebExpo 2010
Elixir Paris Meetup
Symfony2 - OSIDays 2010
Dependency Injection with PHP 5.3
Dirty Secrets of the PHP SOAP Extension
Unit and Functional Testing with Symfony2
Ad

Similar to Sécurisation de vos applications web à l’aide du composant Security de Symfony (20)

PDF
JWT - Sécurisez vos APIs
PDF
How to Build an Indivo X Personal Health App
PDF
OAuth 2.0 and Library
PDF
DEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menace
PPTX
CIS 2012 - Going Mobile with PingFederate and OAuth 2
PPT
Rolebased security
KEY
Phpne august-2012-symfony-components-friends
PPT
Implementing application security using the .net framework
PDF
Building a Microgateway in Ballerina_KubeCon 2108
PDF
WP Passkey: Passwordless Authentication on WordPress
KEY
Building @Anywhere (for TXJS)
PDF
Keeping Pace with OAuth’s Evolving Security Practices.pdf
PDF
Java Web Programming [9/9] : Web Application Security
PPTX
How to implement authorization in your backend with AWS IAM
PDF
Securing your Pulsar Cluster with Vault_Chris Kellogg
PDF
Spring Framework - Spring Security
PDF
Pocket Authentication with OAuth on Firefox OS
PDF
OAuth 2.0 – A standard is coming of age by Uwe Friedrichsen
PPTX
OAuth2 and OpenID with Spring Boot
PPTX
State management
JWT - Sécurisez vos APIs
How to Build an Indivo X Personal Health App
OAuth 2.0 and Library
DEF CON 27 - ALVARO MUNOZ / OLEKSANDR MIROSH - sso wars the token menace
CIS 2012 - Going Mobile with PingFederate and OAuth 2
Rolebased security
Phpne august-2012-symfony-components-friends
Implementing application security using the .net framework
Building a Microgateway in Ballerina_KubeCon 2108
WP Passkey: Passwordless Authentication on WordPress
Building @Anywhere (for TXJS)
Keeping Pace with OAuth’s Evolving Security Practices.pdf
Java Web Programming [9/9] : Web Application Security
How to implement authorization in your backend with AWS IAM
Securing your Pulsar Cluster with Vault_Chris Kellogg
Spring Framework - Spring Security
Pocket Authentication with OAuth on Firefox OS
OAuth 2.0 – A standard is coming of age by Uwe Friedrichsen
OAuth2 and OpenID with Spring Boot
State management
Ad

More from Vladyslav Riabchenko (6)

PPTX
Modèle de domaine riche dans une application métier complexe un exemple pratique
PPTX
SOLID : les principes à l’origine du succès de Symfony et de vos applications
PPTX
Versionning sémantique et Composer
PPTX
Injection de dépendances dans Symfony >= 3.3
PPTX
Les patrons de conception du composant Form
Modèle de domaine riche dans une application métier complexe un exemple pratique
SOLID : les principes à l’origine du succès de Symfony et de vos applications
Versionning sémantique et Composer
Injection de dépendances dans Symfony >= 3.3
Les patrons de conception du composant Form

Recently uploaded (20)

PPTX
Weekly report ppt - harsh dattuprasad patel.pptx
PDF
The Dynamic Duo Transforming Financial Accounting Systems Through Modern Expe...
PPTX
Tech Workshop Escape Room Tech Workshop
PPTX
Cybersecurity: Protecting the Digital World
PDF
Visual explanation of Dijkstra's Algorithm using Python
PDF
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
PDF
Autodesk AutoCAD Crack Free Download 2025
PDF
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
PDF
Website Design Services for Small Businesses.pdf
PDF
Microsoft Office 365 Crack Download Free
PPTX
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
PDF
MCP Security Tutorial - Beginner to Advanced
PDF
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
PDF
Wondershare Recoverit Full Crack New Version (Latest 2025)
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PDF
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
PPTX
Computer Software - Technology and Livelihood Education
PPTX
Trending Python Topics for Data Visualization in 2025
PDF
DuckDuckGo Private Browser Premium APK for Android Crack Latest 2025
Weekly report ppt - harsh dattuprasad patel.pptx
The Dynamic Duo Transforming Financial Accounting Systems Through Modern Expe...
Tech Workshop Escape Room Tech Workshop
Cybersecurity: Protecting the Digital World
Visual explanation of Dijkstra's Algorithm using Python
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
Autodesk AutoCAD Crack Free Download 2025
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
Website Design Services for Small Businesses.pdf
Microsoft Office 365 Crack Download Free
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
MCP Security Tutorial - Beginner to Advanced
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
Wondershare Recoverit Full Crack New Version (Latest 2025)
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
Computer Software - Technology and Livelihood Education
Trending Python Topics for Data Visualization in 2025
DuckDuckGo Private Browser Premium APK for Android Crack Latest 2025

Sécurisation de vos applications web à l’aide du composant Security de Symfony

  • 1. Sécurisation de vos applications web à l’aide du composant Security de Symfony 28 août 2018
  • 2. https://vria.eu contact@vria.eu https://twitter.com/RiaVlad RIABCHENKO Vladyslav 5+ ans full stack web-développeur Certifié Symfony Architecte technique à Webnet
  • 3. Symfony 3 1. Symfony 2. Authentification artisanale 3. Firewall 4. Token anonyme 5. User provider 6. Authentication provider 7. HTTP Basic 8. Formulaire de connexion Plan
  • 4. Symfony 4 Authentification est un processus permettant à l’application de s’assurer que la requête a été faite par un utilisateur légitime. C’est une confirmation de son identité grâce à des identifiants. Identification est une sélection d’utilisateur grâce à son identifiant. Autorisation est une vérification des droits d’accès d’un utilisateur sur une ressource en se basant sur une politique d’accès.
  • 5. Auth simple 5 Authentifier chaque requête à l’application à l’aide d’un identifiant et d’un mot de passe.Tâche 1 Front controller Token public/index.php reçoit toutes les requêtes client quelque soit le path et les paramètres HttpFoundation Composant de Symfony qui fournit la couche orientée-objet pour HTTP : Request, Response, Session, etc. Conserve des données sur l’utilisateur : • Objet d’utilisateur • Username • Credentials • Roles • Authentifié ou pas
  • 6. SymfonyComponentSecurityCoreAuthenticationToken 6 Security listeners Token Conserve des données sur l’utilisateur + getUser() + getUsername() + getCredentials() + isAuthenticated() + getRoles() TokenInterface + getProviderKey() UsernamePasswordToken + getSecret() AnonymousToken Listeners qui extraient les identifiants et les vérifient. Ils créent ensuite un Token puis le stockent dans le Token storage. Token storage Objet/service qui contient un Token Auth simple
  • 7. 7 // public/index.php use SymfonyComponentHttpFoundationRequest; use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorage; use SymfonyComponentHttpFoundationResponse; $request = Request::createFromGlobals(); // HTTP request $tokenStorage = new TokenStorage(); // Service that stores user token // Call security listener on every request. $securityListener = new AppSecuritySecurityListener($tokenStorage); $securityListener->onRequest($request); // Any code you can imagine to generate a response. // You can deny access if no token were set. $token = $tokenStorage->getToken(); $response = new Response( 'Request uri: '.$request->getRequestUri().'<br>' .'Token: '.(is_object($token) ? get_class($token) : gettype($token)).'<br>' .'Username: '.($token ? $token->getUsername(): 'NULL') ); $response->send(); // Send response Auth simple
  • 8. 8 use SymfonyComponentHttpFoundationRequest; use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorageInterface; use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken; class SecurityListener { private $tokenStorage; public function __construct(TokenStorageInterface $tokenStorage) { $this->tokenStorage = $tokenStorage; } public function onRequest(Request $request) { $user = $request->query->get('auth_user'); $password = $request->query->get('auth_pw'); if ($user === 'vlad' && $password === 'pass') { // Credentials are valid. // Create a token with user object, credentials, provider key and roles $token = new UsernamePasswordToken($user, $password, 'main', ['ROLE_USER']); // Save it to token storage $this->tokenStorage->setToken($token); } } } Auth simple
  • 9. Firewall 9 Centraliser l’authentification dans un firewall afin de pouvoir utiliser plusieurs systèmes d’authentification.Tâche 2 HttpKernel Le composant de Symfony qui fournit un processus structuré pour convertir Request en Response en utilisant EventDispatcher. EventDispatcher Le composant de Symfony qui permet aux composants de communiquer entre eux à l’aide d’événements. Request ResponseResolve controller Execute controller EXCEPTIONEvent Dispatcher
  • 10. // public/index.php use SymfonyComponentEventDispatcherEventDispatcher; use SymfonyComponentHttpFoundationRequest; use SymfonyComponentHttpKernelHttpKernel; use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorage; $request = Request::createFromGlobals(); // HTTP request. $tokenStorage = new TokenStorage(); // Service that stores user token. $dispatcher = new EventDispatcher(); // Controller creates a response to send to the user. $controller = new AppController($request, $tokenStorage); $controllerResolver = new AppControllerResolver([$controller, 'defaultAction']); // kernel is in charge of converting a Request into a Response by using the event dispatcher. $kernel = new HttpKernel($dispatcher, $controllerResolver); // We will add security listeners to dispatcher in few minutes. $response = $kernel->handle($request); $response->send(); 10Firewall Le Front controller crée $kernel et lui demande de traiter la requête.
  • 11. 11 Kernel demande à ControllerResolver de renvoyer le contrôleur en fonction de la requête. C’est l’emplacement idéal pour la logique de Routing. use SymfonyComponentHttpFoundationRequest; use SymfonyComponentHttpKernelControllerControllerResolverInterface; class ControllerResolver implements ControllerResolverInterface { /** @var callable */ private $default; public function __construct(callable $default) { $this->default = $default; } public function getController(Request $request) { return $this->default; } } Firewall
  • 12. 12 class Controller { /** @var Request */ private $request; /** @var TokenStorageInterface */ private $tokenStorage; public function defaultAction() { $token = $this->tokenStorage->getToken(); return new Response( 'Request uri: '.$this->request->getRequestUri().'<br>' .'Token: '.(is_object($token) ? get_class($token) : gettype($token)).'<br>' .'Username: '.($token ? $token->getUsername(): 'NULL') ); } } La méthode Controller::defaultAction est un contrôleur qui sera exécuté par Kernel. Firewall
  • 13. SymfonyComponentSecurityHttp 13 - map: array + getListeners(Request $request) Firewall - map: FirewallMap + onKernelRequest(GetResponseEvent $event) FirewallMap RequestMatcher - path: string => ][ Le firewall est un listener de l’événement REQUEST. Il permet d’implémenter des stratégies d’authentification en fonction de la requête. FirewallMap renvoie les listeners configurés pour le requête spécifique. ListenerInterface + handle(GetResponseEvent $event) , … Firewall
  • 14. 14 RequestMatcher - path = ^/back - ips = [192.0.0.4] => ][ BasicAuthenticationListener RequestMatcher - path: ^/customer => ][ ContextListener , SimpleFormAuthenticationListener RequestMatcher => ][AnonymousAuthenticationListener Utiliser l’authentification HTTP basic pour toutes les requêtes qui commencent par /back Authentifier les requêtes qui commencent par /customer à l’aide d’un formulaire classique Authentifier toutes les autres requêtes comme anonymes Firewall
  • 15. 15 // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewall; use SymfonyComponentSecurityHttpFirewallMap; // ... // Create main security listener that handles authentication. $securityListener = new AppSecurityMainSecurityListener($tokenStorage); // Create firewall map and add main security listener under URLs starting with "/main". $firewallMap = new FirewallMap(); $firewallMap->add(new RequestMatcher('^/main'), [$securityListener]); // Create firewall and add it to dispatcher. $firewall = new Firewall($firewallMap, $dispatcher); $dispatcher->addSubscriber($firewall); // ... Firewall attends l’événement REQUEST pour exécuter MainSecurityListener si le path de la requête commence par /main. Firewall
  • 16. 16 use SymfonyComponentHttpKernelEventGetResponseEvent; use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorageInterface; use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken; use SymfonyComponentSecurityHttpFirewallListenerInterface; class MainSecurityListener implements ListenerInterface { /** @var TokenStorageInterface */ private $tokenStorage; public function handle(GetResponseEvent $event) { $request = $event->getRequest(); $user = $request->query->get('auth_user'); $password = $request->query->get('auth_pw'); if ($user === 'vlad' && $password === 'pass') { $token = new UsernamePasswordToken($user, $password, 'main', ['ROLE_USER']); $this->tokenStorage->setToken($token); } } } MainSecurityListener implémente désormais ListenerInterface. Firewall
  • 17. App SymfonyComponentSecurityHttpFirewall anon. 17 Permettre aux utilisateurs de s’authentifier comme des anonymes.Tâche 3 RequestMatcher - path = ^/main => ][ MainSecurityListener AnonymousAuthenticationListener // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallMap; use SymfonyComponentSecurityHttpFirewallAnonymousAuthenticationListener; // ... // Create a security listener that adds anonymous token if none is already present. $anonListener = new AnonymousAuthenticationListener($tokenStorage, 'secret'); // Create firewall map and add main security listener under URLs starting with "/main". $firewallMap = new FirewallMap(); $firewallMap->add(new RequestMatcher('^/main'), [$securityListener, $anonListener]);
  • 18. User provider 18 Abstraire le moyen de récupération des utilisateurs et déplacer cette logique en dehors des security listeners.Tâche 4 SymfonyComponentSecurityCoreUser UserProviderInterface + loadUserByUsername($username): UserInterface + refreshUser(UserInterface $user) + supportsClass($class) Security Listener - userProvider + loadUserByUsername($username):User UserInterface + getUsername() + getRoles() + getPassword() + getSalt() + eraseCredentials() + isEnabled() UserInMemoryUserProvider
  • 19. 19 use SymfonyComponentHttpKernelEventGetResponseEvent; use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken; use SymfonyComponentSecurityCoreExceptionUsernameNotFoundException; use SymfonyComponentSecurityCoreUserUserProviderInterface; use SymfonyComponentSecurityHttpFirewallListenerInterface; class MainSecurityListener implements ListenerInterface { /** @var UserProviderInterface */ private $userProvider; public function handle(GetResponseEvent $event) { $request = $event->getRequest(); $username = $request->query->get('auth_user'); $password = $request->query->get('auth_pw'); try { $user = $this->userProvider->loadUserByUsername($username); if ($user->getPassword() === $password) { $token = new UsernamePasswordToken($user, $password, 'main', $user->getRoles()); $this->tokenStorage->setToken($token); } } catch (UsernameNotFoundException $e) { } } } User provider
  • 20. 20 // public/index.php use SymfonyComponentEventDispatcherEventDispatcher; use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallMap; use SymfonyComponentSecurityHttpFirewall; use SymfonyComponentSecurityCoreUserInMemoryUserProvider; // ... // Create user provider that will be used by authentication listener. $mainUserProvider = new InMemoryUserProvider([ 'vlad' => ['password' => 'pass', 'roles' => ['ROLE_USER’]], ]); // Create main security listener that handles authentication. $mainSecurityListener = new AppSecurityMainSecurityListener($tokenStorage, $mainUserProvider); // Create firewall map and add main security listener under URLs starting with "/main". $firewallMap = new FirewallMap(); $firewallMap->add(new RequestMatcher('^/main'), [$mainSecurityListener, $anonListener]); // ... User provider Création d’un user provider pour main security listener.
  • 21. App 21Auth provider Ajouter l’encodage du mot de passe, n’accepter que des utilisateurs activés. Déplacer la logique d’authentification en dehors des security listeners.Tâche 5 - tokenStorage - authenticationManager SymfonyComponentSecurityCoreAuthentication AuthenticationManagerInterface + authenticate(TokenInterface $token) MainSecurityListener ̶ Être rappelé par Firewall pendant l’événement REQUEST ̶ Extraire l’identifiant et le mot de passe ̶ Créer le token non authentifié ̶ Passer le token à l’authentification manager ̶ Mettre le token authentifié dans le token storage ̶ Récupérer l’utilisateur grâce à l’identifiant et à l’aide de user provider ̶ Vérifier le mot de passe à l’aide de password encoder ̶ Vérifier les autres paramètres ̶ Renvoyer le token authentifié $token->setAuthenticated(true) créer un nouveau token
  • 22. SymfonyComponentSecurityCoreAuthentication 22Auth provider Provider DaoAuthenticationProvider - userProvider - encoderFactory - userChecker AuthenticationManagerInterface + authenticate(TokenInterface $token) SymfonyComponentSecurityCoreUser UserProviderInterface + loadUserByUsername($username) + refreshUser(UserInterface $user) + supportsClass($class) + loadUserByUsername($username):User InMemoryUserProvider
  • 23. SymfonyComponentSecurityCoreAuthentication 23Auth provider Provider DaoAuthenticationProvider - userProvider - encoderFactory - userChecker SymfonyComponentSecurityCoreEncoder EncoderFactoryInterface + getEncoder($user): PasswordEncoderInterface PasswordEncoderInterface + encodePassword($raw, $salt) + isPasswordValid($encoded, $raw, $salt) - cost: int BCryptPasswordEncoder - encoders: array EncoderFactory
  • 24. SymfonyComponentSecurityCoreAuthentication 24Auth provider Provider DaoAuthenticationProvider AuthenticationManagerInterface + authenticate(TokenInterface $token) SymfonyComponentSecurityCoreUser UserChecker + checkPreAuth(UserInterface $user) + checkPostAuth(UserInterface $user) UserCheckerInterface - userProvider - encoderFactory - userChecker
  • 25. 25Auth provider use SymfonyComponentSecurityCoreAuthenticationAuthenticationManagerInterface; use SymfonyComponentSecurityCoreAuthenticationTokenUsernamePasswordToken; use SymfonyComponentSecurityCoreExceptionAuthenticationException; class MainSecurityListener implements ListenerInterface { /** @var AuthenticationManagerInterface */ private $authenticationManager; public function handle(GetResponseEvent $event) { // Extract authentication credentials. if ($username && $credentials) { try { // Token is not authenticated because no role is passed. $token = new UsernamePasswordToken($username, $credentials, 'main'); // Try to authenticate the token. // If there is an authentication error an AuthenticationException is thrown. $token = $this->authenticationManager->authenticate($token); // Add authenticated token to storage. $this->tokenStorage->setToken($token); } catch (AuthenticationException $e) {} } } }
  • 26. 26Auth provider use SymfonyComponentSecurityCoreAuthenticationProviderDaoAuthenticationProvider; use SymfonyComponentSecurityCoreEncoderBCryptPasswordEncoder; // Create user provider that will be used by authentication listener. $mainUserProvider = new InMemoryUserProvider([ 'vlad' => [ 'password' => '$2y$10$zDUW3BF4T5ZVloDZqp0SN.1Ic4DG3xfxHUDXWkkpvaP0G8qXnq', // encoded 'pass' 'roles' => ['ROLE_USER'], 'enabled' => true ] ]); // And object that checks whether a user is non-locked, enabled, not expired, etc. $mainUserChecker = new SymfonyComponentSecurityCoreUserUserChecker(); // A factory that specifies encoding algorithm to each user class. $encoderFactory = new SymfonyComponentSecurityCoreEncoderEncoderFactory([ SymfonyComponentSecurityCoreUserUser::class => new BCryptPasswordEncoder(10) ]); // Create a provider to which security listener will delegate an authentication. $mainAuthProvider = new DaoAuthenticationProvider( $mainUserProvider, $mainUserChecker, 'main', $encoderFactory ); // Create main security listener that handles authentication. $mainSecurityListener = new AppSecurityMainSecurityListener($tokenStorage, $mainAuthProvider);
  • 27. 27HTTP basic auth Mettre en place l’authentification HTTP, laisser passer seulement les utilisateurs connectés.Tâche 6 SymfonyComponentSecurityHttpFirewall - tokenStorage - authenticationManager BasicAuthenticationListener - tokenStorage - accessDecisionManager AccessListener RequestMatcher - path: ^/main => Extraire l’identifiant et le mot de passe de l'en-tête Authorization. Créer le token, l'authentifier, le sauvegarder dans token storage. Lancer une exception si les credentials ne sont pas valides. Lancer une exception si le token n’est pas présent ou s’il ne respecte pas les règles d’accès.
  • 28. 28 SymfonyComponentSecurityHttpEntryPoint + start(Request $request, $authException): Response AuthenticationEntryPointInterface - realmName: string BasicAuthenticationEntryPoint Lors de l'exception d’authentification (accès anonyme ou identifiants non valides) il faut aider l’utilisateur à (re-)commencer l’authentification. SymfonyComponentSecurityHttpFirewall - tokenStorage - authenticationManager - authenticationEntryPoint BasicAuthenticationListener Event Dispatcher - Kernel::EXCEPTION => [...] - authenticationEntryPoint ExceptionListener HTTP basic auth
  • 29. 29 use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpAccessMap; use SymfonyComponentSecurityHttpFirewallMap; use SymfonyComponentSecurityHttpFirewallBasicAuthenticationListener; use SymfonyComponentSecurityHttpFirewallAccessListener; use SymfonyComponentSecurityHttpEntryPointBasicAuthenticationEntryPoint; use SymfonyComponentSecurityCoreAuthorizationAccessDecisionManager; // Entry point helps user to authenticate. $basicAuthenticationEntryPoint = new BasicAuthenticationEntryPoint('Secured area'); // Create HTTP basic security listener that extracts credentials from headers (RFC 7617). $mainSecurityListener = new BasicAuthenticationListener( $tokenStorage, $mainAuthProvider, 'main', $basicAuthenticationEntryPoint ); // Access listener will throw an exception when no token is already present. $accessDecisionManager = new AccessDecisionManager(); $accessMap = new AccessMap(); $accessListener = new AccessListener( $tokenStorage, $accessDecisionManager, $accessMap, $mainAuthProvider ); // Create firewall map and add main security listener under URLs starting with "/main". $firewallMap = new FirewallMap(); $firewallMap->add(new RequestMatcher('^/main'), [$mainSecurityListener, $accessListener]); // ... HTTP basic auth
  • 30. 30 use SymfonyComponentSecurityHttpHttpUtils; use SymfonyComponentSecurityCoreAuthenticationAuthenticationTrustResolver; use SymfonyComponentSecurityCoreAuthenticationTokenAnonymousToken; use SymfonyComponentSecurityCoreAuthenticationTokenRememberMeToken; use SymfonyComponentHttpKernelKernelEvents; // ... // ExceptionListener catches authentication exception and converts them to Response instance. // In this case it invites user to enter its credentials by returning 401 response. $authTrustResolver = new AuthenticationTrustResolver(AnonymousToken::class, RememberMeToken::class); $httpUtils = new HttpUtils(); $exceptionListener = new ExceptionListener( $tokenStorage, $authTrustResolver, $httpUtils, 'main', $basicAuthenticationEntryPoint ); $dispatcher->addListener(KernelEvents::EXCEPTION, array($exceptionListener, 'onKernelException'), 1); // ... HTTP basic auth
  • 31. 31Formulaire de connexion Mettre en place l’authentification par le formulaire de connexion pour une autre partie de site.Tâche 7 SymfonyComponentSecurityHttpFirewall - tokenStorage - userProviders ContextListener - tokenStorage - accessDecisionManager - options - successHandler - failureHandler UsernamePasswordFormAuthenticationListener RequestMatcher - path: ^/front => + handle(GetResponseEvent $event) + onKernelResponse(FilterResponseEvent $event) + handle(GetResponseEvent $event) Récupérer le token d’une session lors de l’événement REQUEST. Sauvegarder le token dans une session lors de l’événement RESPONSE. Authentifier l’utilisateur seulement quand le formulaire de connexion est envoyé (POST sur /front/login_check).
  • 32. 32Formulaire de connexion use SymfonyComponentHttpFoundationResponse; class Controller { public function loginFormAction() { return new Response(<<<END <form action="/front/login_check" method="POST"> <input type="text" name="_username" placeholder="username"> <input type="password" name="_password" placeholder="password"> <input type="submit"> </form> END ); } public function defaultAction() { $token = $this->tokenStorage->getToken(); $user = $token ? $token->getUser() : null; // ... } } Nouvelle action pour visualiser le formulaire de conexion : POST sur /front/login_check.
  • 33. 33Formulaire de connexion use SymfonyComponentHttpFoundationRequest; use SymfonyComponentHttpKernelControllerControllerResolverInterface; class ControllerResolver implements ControllerResolverInterface { /** @var callable[] */ private $routes; /** @var callable */ private $default; public function getController(Request $request) { foreach ($this->routes as $pattern => $controller) { if (preg_match($pattern, $request->getPathInfo())) { return $controller; } } return $this->default; } } La nouvelle action sera appelée quand la requête est faite sur /font/login.
  • 34. 34Formulaire de connexion // public/index.php use SymfonyComponentEventDispatcherEventDispatcher; use SymfonyComponentHttpKernelHttpKernel; // ... // Controller creates a response to send to the user. $controller = new AppController($request, $tokenStorage); $controllerResolver = new AppControllerResolver( ['/^/front/login$/' => [$controller, 'loginFormAction']], [$controller, 'defaultAction'] ); // Kernel is in charge of converting a Request into a Response by using the event dispatcher. $kernel = new HttpKernel($dispatcher, $controllerResolver); // ... La nouvelle action sera appelée quand la requête est faite sur /font/login.
  • 35. 35Formulaire de connexion // public/index.php use SymfonyComponentSecurityHttpFirewallContextListener; // ... // ContextListener retrieves previously authenticated token from the session during REQUEST event. // It also saves token during RESPONSE event. $contextListener = new ContextListener( $tokenStorage, [$mainUserProvider], 'front', null, $dispatcher ); // ... Context security listener :
  • 36. 36Formulaire de connexion use SymfonyComponentSecurityHttpAuthenticationDefaultAuthenticationSuccessHandler; use SymfonyComponentSecurityHttpAuthentication DefaultAuthenticationFailureHandler; use SymfonyComponentSecurityHttpFirewallUsernamePasswordFormAuthenticationListener; use SymfonyComponentSecurityHttpSessionSessionAuthenticationStrategy; $sessionAuthenticationStrategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE); $successHandler = new DefaultAuthenticationSuccessHandler( $httpUtils, ['default_target_path' => '/front/success’] ); $failureHandler = new DefaultAuthenticationFailureHandler( $kernel, $httpUtils, ['login_path' => '/front/login’] ); // Listens for login form being send (POST to '/front/login_check'). // It extracts credentials, creates token, authenticates it and puts it to the token storage. $formAuthListener = new UsernamePasswordFormAuthenticationListener( $tokenStorage, $frontAuthProvider, $sessionAuthenticationStrategy, $httpUtils, 'front', $successHandler, // Redirect user to '/front/success' if credentials are valid $failureHandler, // Redirect user to '/front/login' if credentials are invalid ['check_path' => '/front/login_check’, 'post_only' => true] // Act only on POST to '/front/login_check' );
  • 37. 37Formulaire de connexion // public/index.php use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallMap; // ... $firewallMap = new FirewallMap(); $firewallMap->add(new RequestMatcher('^/main'), [$mainSecurityListener, $accessListener]); $firewallMap->add(new RequestMatcher('^/front'), [$contextListener, $formAuthListener]); // ... Ajout de security listeners dans le Firewall :
  • 38. Merci pour votre attention Le code de cette présentation : https://github.com/vria/symfony-security-component-use