Symfony 4.0
Ten proces nie zmienił się z symfony 3 na 4, ale tutaj jest przykład używający nowo zalecanego AbstractController. Zarówno usługa, jak security.token_storage
i session
usługi są zarejestrowane w getSubscribedServices
metodzie nadrzędnej , więc nie musisz ich dodawać w kontrolerze.
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use YourNameSpace\UserBundle\Entity\User;
class LoginController extends AbstractController{
public function registerAction()
{
$user = //Handle getting or creating the user entity likely with a posted form
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->container->get('security.token_storage')->setToken($token);
$this->container->get('session')->set('_security_main', serialize($token));
// The user is now logged in, you can redirect or do whatever.
}
}
Symfony 2.6.x - Symfony 3.0.x
Od Symfony 2.6 security.context
jest przestarzałe na korzyść security.token_storage
. Teraz kontroler może być po prostu:
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use YourNameSpace\UserBundle\Entity\User;
class LoginController extends Controller{
public function registerAction()
{
$user = //Handle getting or creating the user entity likely with a posted form
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.token_storage')->setToken($token);
$this->get('session')->set('_security_main', serialize($token));
}
}
Chociaż jest to przestarzałe, nadal możesz z niego korzystać, security.context
ponieważ zostało utworzone jako zgodne z poprzednimi wersjami. Po prostu bądź gotowy, aby zaktualizować go do Symfony 3
Możesz przeczytać więcej o zmianach w 2.6 dla bezpieczeństwa tutaj: https://github.com/symfony/symfony/blob/2.6/UPGRADE-2.6.md
Symfony 2.3.x
Aby to osiągnąć w symfony 2.3, nie możesz już po prostu ustawić tokena w kontekście bezpieczeństwa. Musisz również zapisać token w sesji.
Zakładając plik bezpieczeństwa z zaporą ogniową, taką jak:
// app/config/security.yml
security:
firewalls:
main:
//firewall settings here
A akcja kontrolera też jest podobna:
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use YourNameSpace\UserBundle\Entity\User;
class LoginController extends Controller{
public function registerAction()
{
$user = //Handle getting or creating the user entity likely with a posted form
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.context')->setToken($token);
$this->get('session')->set('_security_main',serialize($token));
//Now you can redirect where ever you need and the user will be logged in
}
}
Aby utworzyć token, będziesz chciał utworzyć UsernamePasswordToken
, To akceptuje 4 parametry: Jednostka użytkownika, Poświadczenia użytkownika, Nazwa zapory, Role użytkownika. Nie musisz podawać poświadczeń użytkownika, aby token był ważny.
Nie jestem w 100% pewien, czy ustawienie tokena na to security.context
jest konieczne, jeśli zamierzasz od razu przekierować. Ale to nie wydaje się boleć, więc zostawiłem to.
Następnie ważna część, ustawienie zmiennej sesji. Po konwencji nazewnictwa zmiennych _security_
następuje nazwa zapory, w tym przypadku main
tworzona_security_main
$this->get('session')->set('_security_main', serialize($token));
. Dziękuję @Chausser!main
ORAZ jesteś uwierzytelniony za pomocą innego firewalla o nazwieadmin
(jako że podszywasz się pod użytkownika), dzieje się dziwna rzecz:_security_admin
dostaje sięUsernamePasswordToken
z podanym użytkownikiem, tzn. Zostajesz "rozłączony" Twójadmin
firewall. Masz jakiś pomysł, jak zachować token dla zapory "administratora"?setToken(..)
pod tą samą docelową zaporą ogniową lub bez uwierzytelnienia .W końcu to rozgryzłem.
Po rejestracji użytkownika powinieneś mieć dostęp do instancji obiektu, którą ustawiłeś jako encję użytkownika w konfiguracji dostawcy. Rozwiązaniem jest utworzenie nowego tokenu z tą jednostką użytkownika i przekazanie go do kontekstu zabezpieczeń. Oto przykład oparty na mojej konfiguracji:
RegistrationController.php:
Gdzie
main
jest nazwa zapory sieciowej dla Twojej aplikacji (dzięki, @Joe). To naprawdę wszystko; system traktuje teraz w pełni zalogowanego użytkownika jako użytkownika, którego właśnie utworzył.EDYCJA: Zgodnie z komentarzem @ Miquel zaktualizowałem przykładowy kod kontrolera, aby uwzględnić rozsądną domyślną rolę dla nowego użytkownika (choć oczywiście można to dostosować do specyficznych potrzeb aplikacji).
źródło
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
Jeśli masz obiekt UserInterface (i tak powinno być przez większość czasu), możesz chcieć użyć funkcji getRoles, którą implementuje dla ostatniego argumentu. Więc jeśli utworzysz funkcję logUser, powinno to wyglądać tak:
źródło
Używam Symfony 2.2 i moje doświadczenia były nieco inne niż Problematic , więc jest to połączona wersja wszystkich informacji z tego pytania plus część moich własnych.
Myślę, że Joe myli się co do wartości
$providerKey
trzeciego parametruUsernamePasswordToken
konstruktora. Powinien to być klucz dostawcy uwierzytelniania (nie użytkownika). Jest używany przez system uwierzytelniania do rozróżniania tokenów utworzonych dla różnych dostawców. Każdy dostawca, który pochodzi od,UserAuthenticationProvider
będzie uwierzytelniał tylko tokeny, których klucz dostawcy jest zgodny z jego własnym. Na przykładUsernamePasswordFormAuthenticationListener
ustawia klucz tokenu, który tworzy, tak, aby był zgodny z odpowiadającym mu kluczemDaoAuthenticationProvider
. Dzięki temu pojedyncza zapora sieciowa może mieć wielu dostawców nazw użytkowników i haseł bez wzajemnego nadeptywania. Dlatego musimy wybrać klucz, który nie będzie kolidował z żadnym innym dostawcą. Używam'new_user'
.Mam kilka systemów w innych częściach mojej aplikacji, które zależą od zdarzenia pomyślnego uwierzytelnienia i nie są uruchamiane przez samo ustawienie tokenu w kontekście. Musiałem wyjąć plik
EventDispatcher
z kontenera i ręcznie odpalić zdarzenie. Zdecydowałem się nie uruchamiać również interaktywnego zdarzenia logowania, ponieważ uwierzytelniamy użytkownika niejawnie, a nie w odpowiedzi na jawne żądanie logowania.Zauważ, że użycie of
$this->get( .. )
zakłada, że fragment kodu jest metodą kontrolera. Jeśli używasz kodu w innym miejscu, będziesz musiał zmienić je, aby wywoływałyContainerInterface::get( ... )
w sposób odpowiedni dla środowiska. Tak się składa, że moje encje użytkowników są implementowane,UserInterface
więc mogę ich używać bezpośrednio z tokenem. Jeśli nie masz, musisz znaleźć sposób na ich konwersjęUserInterface
instancje.Ten kod działa, ale wydaje mi się, że zamiast pracować z nią, hackuje architekturę uwierzytelniania Symfony. Prawdopodobnie bardziej poprawne byłoby zaimplementowanie nowego dostawcy uwierzytelniania z własną klasą tokenów, zamiast przechwytywania
UsernamePasswordToken
. Ponadto użycie odpowiedniego dostawcy oznaczałoby, że zdarzenia byłyby obsługiwane za Ciebie.źródło
Na wypadek, gdyby ktoś miał to samo pytanie, do którego wracałem tutaj:
Powołanie
wpływa tylko na prąd
security.context
dla używanej trasy.Oznacza to, że możesz zalogować użytkownika tylko z adresu URL znajdującego się pod kontrolą zapory.
(W razie potrzeby dodaj wyjątek dla trasy -
IS_AUTHENTICATED_ANONYMOUSLY
)źródło
W Symfony 4.4 możesz po prostu wykonać następujące czynności w swojej metodzie kontrolera (patrz w dokumentacji Symfony: https://symfony.com/doc/current/security/guard_authentication.html#manually-authenticating-a-user ):
Jedna ważna rzecz, upewnij się, że twoja zapora nie jest ustawiona na
lazy
. Jeśli tak, token nigdy nie zostanie zapisany w sesji i nigdy nie zostaniesz zalogowany.źródło
Jak już wspomniałem Problematic, ten nieuchwytny parametr $ providerKey jest w rzeczywistości niczym innym jak nazwą twojej reguły firewalla, „foobar” w przypadku poniższego przykładu.
źródło
blablabla
jako trzeci parametr do UsernamePasswordToken, to też zadziała? co oznacza ten parametr?Wypróbowałem wszystkie odpowiedzi tutaj i żadna nie działała. Jedynym sposobem, w jaki mogę uwierzytelnić moich użytkowników na kontrolerze, jest wysłanie żądania dodatkowego, a następnie przekierowanie. Oto mój kod, używam silex, ale możesz łatwo dostosować go do symfony2:
źródło
Na Symfony w wersji 2.8.11 (prawdopodobnie działa dla starszych i nowszych wersji), jeśli używasz FOSUserBundle, po prostu zrób to:
Nie ma potrzeby wysyłania zdarzenia, jak widziałem w innych rozwiązaniach.
zainspirowany z FOS \ UserBundle \ Controller \ RegistrationController :: autenticateUser
(z wersji composer.json FOSUserBundle: „friendsofsymfony / user-bundle”: „~ 1.3”)
źródło