IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Filtre Auth avant controller - Forward si nécessaire


Sujet :

Symfony PHP

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 85
    Points : 48
    Points
    48
    Par défaut Filtre Auth avant controller - Forward si nécessaire
    Bonjour, j'aimerai vous évoquer un petit problème qui ne doit être bien méchant mais il me manque un quelque chose que je ne saisit pas.

    Ce que j'essaye de mettre en place :

    - Mettre un filtre qui n'autorise pas l'accès aux service demandé si l'utilisateur n'est pas connu de la base de donnée (soit, enregistré)
    - Ce filtre redirige vers la page d'accueil pour que l'anonyme se loggue/S'inscrive si ce n'est déjà fait
    - Après être connu loggué/enregistrer, il est redirigé vers sa page qu'il souhaité.

    Ce que j'ai déjà fait :

    Mis en place le filtre. (Je travail avec le framework symfony 2; Php 5; Pgsql, annotation)

    J'ai suivis cette procédure très intéressante expliqué sur cette page qui est aussi expliqué d'une autre manière que le site de symfony.

    L'idée suggéré est de lier un Listener à un controller auquel on va rattaché un service, donc une méthode, qui sera appellé avant chaque action désiré de ce controller. En d'autre termes, à chaque fois que l'on fera appel à un service dans ce controller, une méthode sera exécuté avant (ici, preExecute).

    La méthode preExecute que j'ai écrite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public function preExecute()
    	{
    		$logger = $this->get('logger');
    		$logger->info('Slug '.__CLASS__.' preExecute : start');
    		$user = $this->container->get('security.context')->getToken()->getUser();
    		// Pour vérifier que l'utilisateur est authentifié (et non un anonyme)
    		if( ! is_object($user) )
    		{
    			throw new AccessDeniedException('Vous n\'êtes pas authentifié.');
    		}
    		$logger->info('Slug '.__CLASS__.' preExecute : end');
    	}
    Cela me redirige bien vers ma page d'accueil si l'utilisateur n'est connu à travers l'exception émise qui du coup ne redirige nulle par et qui par défaut est orienté vers ma page de login (action nommé "start") suite a la config effectué dans le fichier security.yml
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        firewalls:
            main:
                pattern: ^.*
                form_login:
                    provider: fos_userbundle
                    login_path: fos_user_security_login
                    check_path: fos_user_security_check
                    csrf_provider: form.csrf_provider
                    default_target_path:    start
    Hors j'ai essayé d'autre manière plutôt de que de faire un "crash" et que ce soit le système de sécurité qui sache faire plutôt que ma fonction. (même si l'auto-délation est intéressante aussi)

    Je voulais tenter ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    public function preExecute()
    	{
    		$logger = $this->get('logger');
    		try
    		{
    			$logger->info('Slug '.__CLASS__.' preExecute : start');
     
    			$user = $this->container->get('security.context')->getToken()->getUser();
     
    			if( ! is_object($user) )
    			{
    				throw new AccessDeniedException('Vous n\'êtes pas authentifié.');
    			}
    			$logger->info('Slug '.__CLASS__.' preExecute : end');
     
    		}catch (\Exception $e)
    		{
    			$logger->info('Slug '.__CLASS__.' preExecute : fail _ '.$e);
     
    			//$uri = $this->generateUrl('start');	    	
    	    	//return $this->redirect($uri);
     
    	    	$response = $this->forward('PldSlugBundle:Default:index');	
    	    	return $response;
    		}
    	}
    Il se passe que si je ne suis authentifié est que j'accéde à une url nommé "B" soumis à l'écoute de ce filtre, la fonction preExecute le détecte et entre dans le catch puis forward vers ma page "login" mais appel après l'url "B". Donc en fait ma fonction ne sert à rien..

    Dans le premier cas, il n'y a pas de catch donc le processus plante et on est redirigé de part la config de sécurité vers la page login.
    Dans le deuxième cas l’exception n'est pas bloquante donc le processus se poursuit.

    C'est ici que je ne comprend pas, j'aurai pensé que dès lors que j'aurai retourné une "réponse" mon service "B" n'aurait été appelé, hors c'est le cas.

    Comment faire pour effectuer cette redirection avec un catch ?

    Je précise que si je fait la redirection dans ma condition if (! isObject($user)) cela revient au même.

    Puis ensuite j'aimerai bien qu'après s'être loggué le service demandé "B" soit "automatiquement" rappelé (suite à une redirection sans doute).
    J'avais pensé à un truc du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $response = $this->forward('PldSlugBundle:Default:index',(array($url->url)));	
    	    	return $response;
    Mais comment la fonction preExecute peut bien connaitre le service demandé ? donc je ne vois pas bien...
    Puis transité cette url à travers FOsUserBundle n'est peut-être pas aussi simple..

    Si vous auriez des idées pour répondre à ces problématiques, je vous en remercie d'avance.

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Septembre 2009
    Messages : 875
    Points : 1 313
    Points
    1 313
    Par défaut
    - Mettre un filtre qui n'autorise pas l'accès aux service demandé si l'utilisateur n'est pas connu de la base de donnée (soit, enregistré)
    - Ce filtre redirige vers la page d'accueil pour que l'anonyme se loggue/S'inscrive si ce n'est déjà fait
    - Après être connu loggué/enregistrer, il est redirigé vers sa page qu'il souhaité.

    Euh, tout ca est géré par la sécurité de base non?
    Regarde http://symfony.com/fr/doc/current/re.../security.html

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    form_login:
                    # Soumet le formulaire de connection ici
                    check_path: /login_check
    
                    # l'utilisateur est redirigé ici si il/elle a besoin de se connecter
                    login_path: /login
    
                    # si true, l'utilisateur est envoyé au formulaire de connexion et non redirigé
                    use_forward: false
    
                    # Les options de redirection en cas de succès de connexion (lire plus bas)
                    always_use_default_target_path: false
                    default_target_path:            /
                    target_path_parameter:          _target_path
                    use_referer:                    false
    
                    # Les options de redirection en cas d'échec de connexion (lire plus bas)
                    failure_path:    /foo
                    failure_forward: false

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 85
    Points : 48
    Points
    48
    Par défaut
    WaaaW, j'ai fait un système, qui pouvait être configuré par un fichier, malheur. Merci de cette réponse.

    En effet tu as bien compris, je n'ai pas très bien maitrisé cette configuration de firewall. Qui semblait correct au début mais après, je n'ai pas réussis à y parvenir surtout en intégrant fosUserBundle puis la notion de _Locale.

    Alors pour info mon listener me fait tout bien comme je veux.

    En revanche je suis pour le fait que ce soit le Firewall qui le gère et non moins un controller via service.

    Voici mon fichier security.yml

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
    security:
        encoders:
           FOS\UserBundle\Model\UserInterface: sha512
           #Symfony\Component\Security\Core\User\User: plaintext
     
        role_hierarchy:
           # ROLE_ADMIN:       ROLE_USER
           # ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
            ROLE_ADMIN:       ROLE_USER
            ROLE_SUPER_ADMIN: ROLE_ADMIN
     
        providers:
            fos_userbundle:
                id: fos_user.user_manager
            in_memory:
                users:
                    user:  { password: userpass, roles: [ 'ROLE_USER' ] }
                    admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
     
        firewalls:
            main:
                pattern: ^.*
                form_login:
                    provider: fos_userbundle
                    login_path: fos_user_security_login
                    check_path: fos_user_security_check
                    csrf_provider: form.csrf_provider
                    default_target_path:    start
     
                logout:
                    path:   fos_user_security_logout
                    target: start
                anonymous:    true
     
            dev:
                pattern:  ^/(_(profiler|wdt)|css|images|js)/
                security: false
     
            login:
                pattern:  ^/demo/secured/login$
                security: false
     
            secured_area:
                pattern:    ^/demo/secured/
                form_login:
                    check_path: /demo/secured/login_check
                    login_path: /demo/secured/login
                logout:
                    path:   /demo/secured/logout
                    target: /demo/
                #anonymous: ~
                #http_basic:
                #    realm: "Secured Demo Area"
     
        access_control:
            #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
            #- { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
     
            - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/admin/, role: ROLE_ADMIN }
    Il n'est pas très robuste.

    - à noté le provider : id: fos_user.user_manager
    - Le patern du firewall : pattern: ^.*

    Maintenant si j’enlève mon filter et ajoute les éléments que j'ai saisi un peut voici ce qui change :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    firewalls:
            main:
                pattern: ^.*
                form_login:
                    provider: fos_userbundle
                    login_path: fos_user_security_login
                    check_path: fos_user_security_check
                    csrf_provider: form.csrf_provider
                    #default_target_path:    start
                    # si true, l'utilisateur est envoyé au formulaire de connexion et non redirigé
                    use_forward: false
     
                    # Les options de redirection en cas de succès de connexion (lire plus bas)
                    always_use_default_target_path: false
                    default_target_path:            start
                    target_path_parameter:          _target_path
                    use_referer:                    false
                    # Les options de redirection en cas d'échec de connexion (lire plus bas)
                    failure_path:    start
                    failure_forward: false
                logout:
                    path:   fos_user_security_logout
                    target: start
                anonymous:    true
    Je n'ai pas très bien saisis cette notion "use_forward" ;
    use_forward (type: Boolean, default: false) Si vous voulez que l'utilisateur soit « forwardé » vers le formulaire d'authentification au lieu d'être redirigé, définissez cette option à true.

    C'est à dire, on lance une url "www..../jeveuxça", si non connu, retour à www..../login
    ou
    on lance une url "www..../jeveuxça", si non connu, retour à www..../login et si login ok renvoi à "www..../jeveuxça" ?

    Le problème est que toutes mes pages sont accessibles de manière anonymes (plus de filter), la cause du à ceci si je comprend bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    access_control:
            #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
            #- { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
            - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/admin/, role: ROLE_ADMIN }
    Il n'y a pas de restriction de contrôle et dans le firewall j'ai "anonymous: true"

    Alors j'ai voulu faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    - { path: ^/[a-z][a-z], role: ROLE_USER }
    - { path: ^/[a-z][a-z]/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
    En effet j'ai ma locale. Ma fonction "start" ajoute la locale utilisateur à l'url, puis appel la page de login

    Je passe donc de www..../ à www..../fr/login

    Voici les routes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    PldSlugBundle:
        resource: "@PldSlugBundle/Controller/"
        type:     annotation
        prefix:   /
     
    PldOfferBundle:
        resource: "@PldOfferBundle/Controller/"
        type:     annotation
        prefix:   /{_locale}/Offer
        requirements:
            _locale: en|fr|de
            default: en
     
    PldAccountBundle:
        resource: "@PldAccountBundle/Controller/"
        type:     annotation
        prefix:   /{_locale}/Account
        defaults: {_locale: en}
        requirements:
            _locale: en|fr|de
     
    PldLocalisationBundle:
        resource: "@PldLocalisationBundle/Controller/"
        type:     annotation
        prefix:   /Localisation
     
    fos_js_routing:
        resource: "@FOSJsRoutingBundle/Resources/config/routing/routing.xml"
     
    fos_user_security:
        resource: "@FOSUserBundle/Resources/config/routing/security.xml"
        prefix:   /{_locale}
        requirements:
            _locale: en|fr|de
            default: en
     
    fos_user_profile:
        resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
        prefix: /profile
     
    fos_user_register:
        resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
        prefix: /register
     
    fos_user_resetting:
        resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
        prefix: /resetting
     
    fos_user_change_password:
        resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
        prefix: /change
    NB : c'est dans le Bundle SlugBundle que j'ai ma commande de login et d'accueil.

    Mais j'ai cette erreur :

    Le navigateur a détecté que le serveur redirige la demande pour cette adresse d'une manière qui n'aboutira pas.
    Alors je ne saisis pas, je spécifie que tout url www.../fr|de|en|etc doivent être connu (rôle user) et que celui de /login est accessible à tous, mais ça ne semble aboutir.

    Alors j'ai fait l'inverse :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    - { path: ^/[a-z][a-z]/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/[a-z][a-z], role: ROLE_USER }
    Et là ça fonctionne. (je pensais que ça aurait lu de haut en bas, l'ordre des privilèges)

    Si je tape www...../fr/allerLa et que je ne suis connu je suis redirigé vers www..../fr/login

    J'ai rajouté après :- { path: ^/Localisation, role: ROLE_USER } , pour mes routes à ce niveau.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    - { path: ^/[a-z][a-z]/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/[a-z][a-z]/, role: ROLE_USER }
    - { path: ^/Localisation, role: ROLE_USER }
    Je n'ai pas su saisir ou rediriger les demande qui n’accède pas. Par exemple j'ai fait le test

    www..../deee/login

    cette url n'est pas pris en compte dans le pattern définissant une locale [a-z][a-z], donc aboutira à rien du tout. Rediriger la demande donc vers la page login si anonyme ou accueil si connu. Comment faire ? (après est-ce une bonne idée, ne vaut-il mieux pas créer une page disant, "cette page demandé n'existe pas", comment le configurer donc ?).

    Par contre avec tout ceci, je tombe sur un grand souci. Quand je me connecte avec un compte valide je suis redirigé vers cette adresse :

    (oui je travail en local même si je mets des www.../ en exemple) ave cun charabia pas possible affiché

    Qu'est ce qui c'est passé ? on dirait une redirection qui n'as pas aboutit et qui amène a un callback qui retourne du code bizarre
    fos.Router.setData({"base_url":"\/Symfony\/web\/app_dev.php","routes":{"contact":{"tokens":[["text","\/contact"],["variable","\/","[^\/]+?","_locale"]],"defaults":{"_locale":"en"},"requirements":[]},"lookForByContinent":{"tokens":[["variable","\/","[^\/]+?","name"],["text","\/Offer\/lookForByContinent"
    etc.

    Après quand je relance la page de démarrage, j'arrive bien sur la page d'accueil, m'étant connecté auparavant.

    J'avance un peut, mais ce n'est pas finis, quel serai la procédure et la config "béton" ?

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 85
    Points : 48
    Points
    48
    Par défaut
    Je reviens sur le sujet, car je suis toujours embêté au niveau de la redirection d'url (à travers un premier url demandé non connecté) suite un login succès.

    configuration security.yml

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    firewalls:
            main:
                pattern: ^
                form_login:
                    provider: fos_userbundle
                    login_path: fos_user_security_login
                    check_path: fos_user_security_check
                    csrf_provider: form.csrf_provider
                    default_target_path: start
                logout:
                    path:   fos_user_security_logout
                    target: start
                anonymous:    true
     
            dev:
                pattern:  ^/(_(profiler|wdt)|css|images|js)/
                security: false
     
            login:
                pattern:  ^/demo/secured/login$
                security: false
     
            secured_area:
                pattern:    ^/demo/secured/
                form_login:
                    check_path: /demo/secured/login_check
                    login_path: /demo/secured/login
                logout:
                    path:   /demo/secured/logout
                    target: /demo/
                #anonymous: ~
                #http_basic:
                #    realm: "Secured Demo Area"
     
        access_control:
            #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
            #- { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
     
            - { path: ^/[a-z][a-z]/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/[a-z][a-z], role: ROLE_USER }
            - { path: ^/Localisation, role: ROLE_USER }
            - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/admin/, role: ROLE_ADMIN }
    Je suis anonyme et tape dans url : www...../fr/fiche/11
    Je suis redirigé ver la page login www...../fr/login
    Je m'authentifie avec succès et doit être redirigé vers www......./fr/fiche/11

    mais je suis redirigé vers cette url www...../js/routing?callback=fos.Router.setData
    Et donc ceci en autre est affiche
    fos.Router.setData({"base_url":"\/Symfony\/web\/app_dev.php","routes":{"contact":{"tokens":[["text","\/contact"],["variable","\/","[^\/]+?","_locale"]],"defaults":{"_locale":"en"},"requirements":[]},
    Et d'autre encore, qui représente au bout du compte à des routes de deux bundles que j'ai conçu, c'est étrange ce listing farfouilleux.

    J'utilise en effet fosJsRounting
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    fos_js_routing:
        resource: "@FOSJsRoutingBundle/Resources/config/routing/routing.xml"
    Je ne comprend pas cette erreur.

    Si je tape dans l'url www.../fr/login et me connecte, je suis redirigé vers la page d'accueil comme spécifié dans le fichier sécurité.

    La redirection est automatique par défaut dans la config symfony.

    Sauriez vous pourquoi ce problème de redirection, dès lors que j'ai demandé une page auparavant de m'être connecté ?

Discussions similaires

  1. Appliquer un filtre? (erreur Access-Control-Allow-Origin)
    Par Ma29200 dans le forum GWT et Vaadin
    Réponses: 9
    Dernier message: 21/03/2013, 19h09
  2. Intercaler un filtre sonore avant sortie
    Par jblecanard dans le forum Windows
    Réponses: 0
    Dernier message: 15/06/2010, 15h35
  3. Réponses: 1
    Dernier message: 23/09/2009, 12h17
  4. Aide Winform filtre sql avant affichage datagridview
    Par minette dans le forum Windows Forms
    Réponses: 1
    Dernier message: 13/09/2008, 17h19
  5. Réponses: 21
    Dernier message: 10/05/2006, 14h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo