Reputation: 18660
I'm trying to redirect if a user is not logged in (works with FOSUser and SonataAdmin) and calls either http://domain.com/app_dev.php
(dev) or http://domain.com
(prod) then I want in both cases redirect to /login
so I wrote this config at app/routing.yml
:
root:
path: /
defaults:
_controller: FrameworkBundle:Redirect:urlRedirect
path: /login
permanent: true
That works but I have a problem since I have this in a controller:
/**
* @param Request $request
*
* @return array
* @Route("/", name="brand")
* @Method("GET")
* @Template()
*/
public function indexAction(Request $request)
{
....
}
Then when I try to call brand
route as per example using a link like: http://domain.com/app_dev.php/?email=7x-xRFClkjw
(dev) or http://domain.com/?email=7x-xRFClkjw
(prod) I got redirected to /login
. My best idea is to change my code into this:
/**
* @param Request $request
*
* @return array
* @Route("/bp", name="brand")
* @Method("GET")
* @Template()
*/
public function indexAction(Request $request)
{
....
}
And then redirect using a route to the new /bp
instead to /
for that function (this is mainly because users already has a tons of emails that had links as the previously shared and I can't change that). But I've not idea in how to write this rule in routing.yml
because if I wrote this:
bp:
path: /
defaults:
_controller: FrameworkBundle:Redirect:redirect
route: brand
permanent: true
I will end up with a redirect loop. I could change also how default route to /login
is setup I just can't find the right documentation. The big idea behind this post is to setup default route for /
. Can any give me some help on this?
As extra info this is part of my security.yml
file:
firewalls:
...
admin_area:
pattern: ^/
anonymous: ~
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
# the user is redirected here when they need to log in
login_path: /login
# submit the login form here
check_path: /login_check
# login success redirecting options (read further below)
always_use_default_target_path: true
default_target_path: /admin/dashboard
target_path_parameter: _target_path
use_referer: false
failure_path: /admin/dashboard
failure_forward: false
logout:
path: /logout
UPDATE
Actually the code from @emmanuel-hdz-díaz give me another idea and I don't need to create a kernel listener or add to much code, simple by doing this at my controller:
if ($request->query->get('email')) {
...
} else {
return $this->redirect($this->generateUrl('sonata_user_admin_security_login'));
}
I was able to redirect the user to the /login
route.
Upvotes: 0
Views: 270
Reputation: 1391
Throw a special exception, catch it in the kernel.request event, redirect from there. You have to create a custom exception that you can store your route in.e.g:
class RouteException extends \Exception{
protected $route;
public function __construct($route){
$this->route = $route;
}
public function getRoute() { return $this->route; }
}
Now create a listener that will generate a RedirectResponse
when it detects this exception, e.g:
class RedirectExceptionListener{
protected $router;
public function __construct(RouterInterface $router){
$this->router;
}
public function onException(GetResponseForExceptionEvent $event){
$e = $event->getException();
if($e instanceof RouteException){
$url = $this->router->generate($e->getRoute());
$event->setResponse(
new RedirectResponse($url);
);
}
}
}
# the service definition
your_listener:
class: RedirectExceptionListener
arguments:
- @router
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
Note: you have to use
the namespaces for the used classes.
This is basically what you can do to redirect from anywhere in your application, although it does seem like a smelly use of exceptions, so create a service Redirecter
with a method redirect($route)
that throws the exception for you, so the calling service will not know how the redirection is being done.The Redirecter
can throw the exception or do anything required to redirect to the given route.
For more info on event listeners see Event Listeners.
Update: This is exactly how symfony redirects you to your login_path
when you're not authenticated, see ExceptionListener
Upvotes: 1
Reputation: 191
Try this:
In your controller inside yourAction():
//
$usr = $this->get('security.context')->getToken()->getUser();
if( $usr == 'anon.' )
{
return $this->redirect($this>generateUrl('sonata_user_admin_security_login'));
}
//
Upvotes: 1
Reputation: 5542
Not sure if I understand, but you want to restrict access to whole site? In that case just simply change you security setting, never add redirect to login, because it always redirect to login even if use is logged in. Here is simple configuration example:
security:
firewalls:
main:
pattern: ^/
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, role: ROLE_USER }
Upvotes: 1