2011-11-30 3 views
6

Chcę zmusić użytkownika do używania HTTPS zamiast HTTP, ale tylko po uwierzytelnieniu. Jedyną dostępną opcją jest wymuszenie protokołu HTTPS na podstawie kontrolera/metody. Anonimowi użytkownicy powinni używać tylko protokołu HTTP.Symfony2, przełącz się na HTTPS po uwierzytelnieniu

Jak ustawić siłę https tylko dla uwierzytelnionych użytkowników i siła nie używać HTTPS dla nieuwierzytelnionych użytkowników we wszystkich sterowników w moim zestawie?

Jeszcze raz - nie chodzi o wyłączenie HTTPS dla strony autoryzacji.

Chcę wykorzystać wszystkie te same sterowniki dla uwierzytelnionych i nieuwierzytelnionych użytkowników, ale zmusić tych zalogowany aby skorzystać z protokołu HTTPS, a ci, którzy nie są w użyciu protokołu HTTP. Zasadniczo dodaj wymaganie dla HTTPS dla WSZYSTKICH kontrolerów, gdy użytkownik jest uwierzytelniony.

To pytanie jest specyficzne dla Symfony 2. Chcę to zrobić za pomocą mechanizmów Symfony. Wiem, jak to wykryć, ale przerwie to linki Twig. Symfony może automatycznie przełączać się na HTTPS, chcę tylko wiedzieć, jak to zrobić na podstawie ról dla poszczególnych użytkowników, a nie na podstawie kontrolera.

+0

Masz pytanie? – JJJ

+1

Nie używanie protokołu HTTPS do uwierzytelniania jest decyzją ZŁY. Oznacza to, że dane wysyłane/odbierane są zwykłym tekstem, a każdy, kto ma dostęp do dowolnego komputera na trasie między klientem a serwerem, będzie mógł odczytać pakiety i zebrać dane uwierzytelniające (użytkownik, hasło, plik cookie itp.). Czy istnieje szczególny powód, aby nie używać SSL do uwierzytelniania? – jweyrich

+2

@jweyrich To nie jest pytanie. Chcę, aby użytkownik korzystał z protokołu HTTPS dla wszystkich kolejnych stron po autoryzacji (która jest zewnętrzna btw) i wyłącza https dla nieautoryzowanych użytkowników. –

Odpowiedz

10

Można by pomyśleć kontroler dostępu zrobi to za nas:

access_control: 
    - { role: ROLE_USER, requires_channel: https } 
    - { role: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: http } 

Ale, nie ... Myślę, że to byłoby bardzo miłe funkcję chociaż.

W takim przypadku możemy siekać coś razem z prośbą słuchacz wykorzystaniem zdarzeń jądra:

namespace YourBundle\EventListener; 

use Symfony\Component\HttpKernel\Event\GetResponseEvent; 
use Symfony\Component\HttpFoundation\RedirectResponse; 

class RequestListener 
{ 
    public function onKernelRequest(GetResponseEvent $event) 
    { 
     $request = $event->getRequest(); 

     // force ssl based on authentication 
     if ($this->container->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY')) { 
      if (!$request->isSecure()) { 
       $request->server->set('HTTPS', true); 
       $request->server->set('SERVER_PORT', 443); 
       $event->setResponse(new RedirectResponse($request->getUri())); 
      } 
     } else { 
      if ($request->isSecure()) { 
       $request->server->set('HTTPS', false); 
       $request->server->set('SERVER_PORT', 80); 
       $event->setResponse(new RedirectResponse($request->getUri())); 
      } 
     } 
    } 
} 

Zdefiniuj słuchacza w config.yml ramach usług:

myapp.request.listener: 
    class: MyApp\MyBundle\EventListener\RequestListener 
    tags: 
     - { name: kernel.event_listener, event: kernel.request } 

Zobacz Symfony Internals Szczegółowe informacje na temat wydarzenia i tym podobne.

+1

Możesz sprawdzić nasz pakiet, który pozwala na automatyczne zachowania, takie jak wymuszanie ssl dla zalogowanych użytkowników, bez podawania numeru 403, jeśli uzyskują dostęp do witryny bez https: https://github.com/nelmio/NelmioSecurityBundle – Seldaek

2

W Symfony 2.0.11 pojawia się błąd przekierowania. Aby rozwiązać ten problem, skomentowałem następujące linie w odbiorniku.

class RequestListener { 
    public function onKernelRequest(GetResponseEvent $event) { 
     $request = $event->getRequest(); 

     // force ssl based on authentication 
     if  ($this->container->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY')) { 
      if (!$request->isSecure()) { 
       $request->server->set('HTTPS', true); 
       $request->server->set('SERVER_PORT', 443); 
       // $event->setResponse(new RedirectResponse($request->getUri())); 
      } 
     } else { 
      if ($request->isSecure()) { 
       $request->server->set('HTTPS', false); 
       $request->server->set('SERVER_PORT', 80); 
       // $event->setResponse(new RedirectResponse($request->getUri())); 
      } 
     } 
    } 
}