2012-07-16 12 views
13

में भूमिका के आधार पर अलग-अलग URL पर रीडायरेक्ट करने मैं साइट पर एक प्रवेश पृष्ठ की है। मैं उन के 4 अलग Tye है और मुझे लगता है कि जब वे के लिए लॉग इन वे अपने भूमिका सौंपी के आधार पर भिन्न पृष्ठ पर जाना चाहते हैं।कैसे सिम्फोनी 2

क्या कोई रास्ता है? इस को हल करने के

उत्तर

27

एक तरह से security.interactive_login घटना पर एक घटना श्रोता का प्रयोग है। इस मामले में मैं बस उस घटना श्रोता में एक और श्रोता संलग्न करें ताकि यह प्रतिक्रिया पर सक्रिय होगा। यह प्रमाणीकरण अभी भी होने देता है लेकिन फिर भी पूर्ण होने पर रीडायरेक्ट करता है।

<service id="sotb_core.listener.login" class="SOTB\CoreBundle\EventListener\SecurityListener" scope="request"> 
    <tag name="kernel.event_listener" event="security.interactive_login" method="onSecurityInteractiveLogin"/> 
    <argument type="service" id="router"/> 
    <argument type="service" id="security.context"/> 
    <argument type="service" id="event_dispatcher"/> 
</service> 

और वर्ग ...

class SecurityListener 
{ 
    protected $router; 
    protected $security; 
    protected $dispatcher; 

    public function __construct(Router $router, SecurityContext $security, EventDispatcher $dispatcher) 
    { 
     $this->router = $router; 
     $this->security = $security; 
     $this->dispatcher = $dispatcher; 
    } 

    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) 
    { 
     $this->dispatcher->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse')); 
    } 

    public function onKernelResponse(FilterResponseEvent $event) 
    { 
     if ($this->security->isGranted('ROLE_TEAM')) { 
      $response = new RedirectResponse($this->router->generate('team_homepage')); 
     } elseif ($this->security->isGranted('ROLE_VENDOR')) { 
      $response = new RedirectResponse($this->router->generate('vendor_homepage')); 
     } else { 
      $response = new RedirectResponse($this->router->generate('homepage')); 
     } 

     $event->setResponse($response); 
    } 
} 
+0

अच्छा काम करते हैं, साधारण घटना श्रोता! – pregmatch

+0

सही! त्वरित नोट।श्रोता को पंजीकृत करते समय मुझे स्कोप = अनुरोध को परिभाषित करने की आवश्यकता नहीं थी (symfony2 v 2.4.8)। –

2

आप देख रहे हैं @MDrollette से एक सरल जवाब के लिए, यदि आप अपने प्रवेश सफलता पेज के नियंत्रक में एक ऐसी ही रीडायरेक्ट ब्लॉक डाल सकता है।

4

मैंने मैड्रोललेट उत्तर का उपयोग किया लेकिन इस समाधान में बड़ी कमी आई है, आप पूरी तरह से सिम्फनी मूल प्रतिक्रिया को ओवरराइड करते हैं और ऐसा करके मुझे सिमफ़ोनी द्वारा हेडर में सेट की गई कुकी को याद रखें।

public function onKernelResponse(FilterResponseEvent $event) 
{ 
    if ($this->security->isGranted('ROLE_TEAM')) { 
     $event->getResponse()->headers->set('Location', $this->router->generate('team_homepage'));  
    } elseif ($this->security->isGranted('ROLE_VENDOR')) { 
     $event->getResponse()->headers->set('Location', $this->router->generate('vendor_homepage')); 
    } else { 
     $event->getResponse()->headers->set('Location', $this->router->generate('homepage')); 
    } 
} 

इस तरह आप मुझे बरकरार कुकी याद रहते हैं:

मेरी समाधान OnKernelResponse इस तरह से बदलने के लिए किया गया था।

0

परीक्षण के लिए, यदि आप मूल प्रतिक्रिया आप भी सिर्फ हेडर नकल कर सकता है की रक्षा करने के लिए इच्छुक रहे हैं। रीडायरेक्ट ऑब्जेक्ट पर क्लोन विधि केवल हेडर की प्रतिलिपि बनाता है।

public function onKernelResponse(FilterResponseEvent $event) 
{ 
    if ($this->security->isGranted('ROLE_TEAM')) { 
     $response = new RedirectResponse($this->router->generate('team_homepage')); 
    } elseif ($this->security->isGranted('ROLE_VENDOR')) { 
     $response = new RedirectResponse($this->router->generate('vendor_homepage')); 
    } else { 
     $response = new RedirectResponse($this->router->generate('homepage')); 
    } 

    $response->headers = $response->headers + $event->getResponse()->headers; 

    $event->setResponse($response); 
} 
+0

मुझे त्रुटि मिलती है नोटिस: कक्षा का उद्देश्य सिम्फनी \ घटक \ HttpFoundation \ ResponseHeaderBag को + ऑपरेटर की वजह से int 'में परिवर्तित नहीं किया जा सका? – Permana

9

लिए Symfony> = 2.6 अब किया जाएगा:

<?php 

namespace CommonBundle\Listener; 

use Monolog\Logger; 
use Symfony\Component\EventDispatcher\EventDispatcherInterface; 
use Symfony\Component\HttpKernel\Event\FilterResponseEvent; 
use Symfony\Component\HttpKernel\KernelEvents; 
use Symfony\Component\Routing\Router; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; 
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; 

class LoginListener 
{ 
    /** @var Router */ 
    protected $router; 

    /** @var TokenStorage */ 
    protected $token; 

    /** @var EventDispatcherInterface */ 
    protected $dispatcher; 

    /** @var Logger */ 
    protected $logger; 

    /** 
    * @param Router $router 
    * @param TokenStorage $token 
    * @param EventDispatcherInterface $dispatcher 
    * @param Logger $logger 
    */ 
    public function __construct(Router $router, TokenStorage $token, EventDispatcherInterface $dispatcher, Logger $logger) 
    { 
     $this->router  = $router; 
     $this->token  = $token; 
     $this->dispatcher = $dispatcher; 
     $this->logger  = $logger; 
    } 

    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) 
    { 
     $this->dispatcher->addListener(KernelEvents::RESPONSE, [$this, 'onKernelResponse']); 
    } 

    public function onKernelResponse(FilterResponseEvent $event) 
    { 
     $roles = $this->token->getToken()->getRoles(); 

     $rolesTab = array_map(function($role){ 
      return $role->getRole(); 
     }, $roles); 

     $this->logger->info(var_export($rolesTab, true)); 

     if (in_array('ROLE_ADMIN', $rolesTab) || in_array('ROLE_SUPER_ADMIN', $rolesTab)) { 
      $route = $this->router->generate('backend_homepage'); 
     } elseif (in_array('ROLE_CLIENT', $rolesTab)) { 
      $route = $this->router->generate('frontend_homepage'); 
     } else { 
      $route = $this->router->generate('portal_homepage'); 
     } 

     $event->getResponse()->headers->set('Location', $route); 
    } 
} 

और services.yml

services: 
common.listener.login: 
    class: CommonBundle\Listener\LoginListener 
    arguments: [@router, @security.token_storage, @event_dispatcher, @logger] 
    scope: request 
    tags: 
     - { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin } 
3

Symfony 3.1 में परीक्षण किया गया

तुम भी सेट कर सकते हैं उपयोगकर्ता लॉगिन के बाद डिफ़ॉल्ट पथ सफलतापूर्वक तो जैसे seciurity.yml फ़ाइल में सभी उपयोगकर्ताओं के लिए:

[config/seciurity.yml]

... 

firewalls: 
    # disables authentication for assets and the profiler, adapt it according to your needs 
    dev: 
     pattern: ^/(_(profiler|wdt)|css|images|js)/ 
     security: false 
    main: 
     pattern: /.* 
     form_login: 
      login_path: /login 
      check_path: /login_check 
      default_target_path: /login/redirect <<<<<<<<<<<<<<<<<<<<<<<<< 
     logout: 
      path: /logout 
      target:/
     security: true 
     anonymous: ~ 
... 

और फिर उस स्थान में सरल उपयोगकर्ता भूमिका पर आधारित पुनर्निर्धारण करते हैं। बहुत सीधे आगे। कुछ कहते हैं कि सबसे आसान तरीका हमेशा सबसे अच्छा तरीका है। आप तय :)

[SomeBundle/नियंत्रक/SomeController.php]

/** 
* Redirect users after login based on the granted ROLE 
* @Route("/login/redirect", name="_login_redirect") 
*/ 
public function loginRedirectAction(Request $request) 
{ 

    if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) 
    { 
     return $this->redirectToRoute('_login'); 
     // throw $this->createAccessDeniedException(); 
    } 

    if($this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) 
    { 
     return $this->redirectToRoute('_admin_panel'); 
    } 
    else if($this->get('security.authorization_checker')->isGranted('ROLE_USER')) 
    { 
     return $this->redirectToRoute('_user_panel'); 
    } 
    else 
    { 
     return $this->redirectToRoute('_login'); 
    } 

} 

वर्क्स एक आकर्षण की तरह लेकिन नीचे की ओर मामले में हमेशा सबसे प्रतिबंधित भूमिकाओं के लिए जाँच करने के लिए ध्यान रखें कि आपके ROLE_ADMIN भी की विशेषाधिकार ROLE_USER और इतने पर ...

+0

+1 महान दृष्टिकोण! आपकी कॉन्फ़िगरेशन के आधार पर इसे 'always_use_default_target_path: true' विकल्प भी जोड़ना आवश्यक हो सकता है। – conceptdeluxe

संबंधित मुद्दे