Created
February 25, 2013 07:23
-
-
Save 77web/5028312 to your computer and use it in GitHub Desktop.
How to switch user accounts between two(or more) different firewalls when using Symfony\Bundle\SecurityBundle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//you may have some more configs here... | |
providers: | |
user: | |
entity: { class: MyAppBundle:User, property: loginEmail } | |
admin: | |
entity: { class: MyAppBundle:Admin, property: username } | |
firewalls: | |
dev: | |
pattern: ^/(_(profiler|wdt)|css|images|js)/ | |
security: false | |
login: | |
pattern: /login$ | |
security: false | |
frontend: | |
provider: user | |
anonymous: ~ | |
pattern: ^/user | |
form_login: | |
login_path: /user/login | |
check_path: /user/login_check | |
logout: | |
path: /user/logout | |
target: /user/ | |
backend: | |
provider: admin | |
pattern: ^/admin | |
form_login: | |
login_path: /admin/login | |
check_path: /admin/login_check | |
logout: | |
path: /admin/logout | |
target: /admin/ | |
#anonymous: ~ | |
access_control: | |
- { path: ^/user/switch$, roles: IS_AUTHENTICATED_ANONYMOUSLY } | |
- { path: ^/user, roles: ROLE_USER } | |
- { path: ^/admin, roles: ROLE_ADMIN } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//you may have some more routings here... | |
admin_switch_to_user: | |
pattern: /admin/user/switch/{userId} | |
defaults: { _controller: MyAppBundle:Admin\User:switch } | |
requirements: { userId: integer } | |
user_switch: | |
pattern: /user/switch | |
defaults: { _controller: MyAppBundle:Account:switch } | |
user_switch_exit: | |
pattern: /user/exit_switch | |
defaults: { _controller: MyAppBundle:Account:exitSwitch } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use Symfony\Component\Security\Core\Authentication\UsernamePasswordToken; | |
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; | |
//you may have some more action methods here... | |
public function switchAction() | |
{ | |
if ($this->get('session')->get('userid_to_switch')) | |
{ | |
$user = $this->getDoctrine()->getEntityManager()->find('MyAppBundle:User', $this->get('session')->get('userid_to_switch')); | |
if ($user) | |
{ | |
//create token instance | |
//2nd argument is password, but empty string is accepted | |
//3rd argument is "firewall" name(be careful, not a "provider" name!!! though UsernamePasswordToken.php names it as "providerKey") | |
$token = new UsernamePasswordToken($user, '', 'frontend', $user->getRoles()); | |
//set token instance to security context | |
$this->get('security.context')->setToken($token); | |
//fire a login event | |
$event = new InteractiveLoginEvent($this->getRequest(), $token); | |
$this->get('event_dispatcher')->dispatch('security.interactive_login', $event); | |
//redirect to some user scoped actions | |
return $this->redirect($this->generateUrl('user_homepage')); | |
} | |
} | |
//fallback | |
return $this->redirect($this->generateUrl('admin_homepage')); | |
} | |
public function exitSwitchAction() | |
{ | |
//unset "userid_to_switch" in session to avoid conflicts | |
$this->get('session')->set('userid_to_switch', null); | |
//logout as user | |
$this->get('security.context')->setToken(null); | |
//going back to admin context... | |
return $this->redirect($this->generateUrl('admin_homepage')); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//you may have some more action methods here... | |
public function switchAction($userId) | |
{ | |
//never use the session key "userid_to_switch" in other actions | |
$this->get('session')->set('userid_to_switch', $userId); | |
return $this->redirect($this->generateUrl('user_switch')); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//how to render a link to "exit_switch" in switched user context | |
{% if app.user %} | |
{% if app.session.get('userid_to_switch') %} | |
<a href="{{ path('user_switch_exit') }}">{{ 'Re-switch as admin'|trans }}</a> | |
{% else %} | |
<a href="{{ path('user_logout') }}">{{ 'Logout'|trans }}</a> | |
{% endif %} | |
{% endif %} |
Figured it out - sometime in SF4/SF5 time frame there was a change that checks if the user in the session/token matches the user retrieved from the DB. Because additional roles are added (ROLE_PREVIOUS_ADMIN or IS_IMPERSONATOR) that check fails. I fixed it by implementing the EquatableInterface on the User object and doing my own check. Returning true from there allows it to work as designed above.
@gnat42
Thank you!!
I've totally given up for this in SF4, but your advice enables it again!
No problem!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Not sure why but this has stopped working for me in SF5. Investigating the issue...