Zend Framework 2 : Check request URI matched against registered Router
When you develop web application using Zend Framework 2, there is sometime you get the situation that you need to check requested URI matched against registered ‘Router’, for example : you have uri : http://zf2app/register?redirect=/user which the application will redirect to passed ‘redirect’ parameter. What if user make bypassed and inject unexpected
redirect
param ? For example, you have code like this in your controller action :
$redirect = $this->params()->fromQuery('redirect',''); return $this->redirect()->toUrl($redirect);
We can inject unwanted redirect into browser, and BOOM, the site will be redirected to unwanted uri. So, we need to handle it! we need to check whenever the ‘redirect’ value can be matched with registered Router
.
First, check if the request URI can be matched against registered Router.
$redirect = $this->params()->fromQuery('redirect',''); $request = $this->getRequest(); $request->setUri($redirect); // assignment, not Comparison, that's why use single '=' if ($routeToBeMatched = $this->getServiceLocator()->get('Router')->match($request)) { // ... process redirection based on 'redirect' param... }
When request URI matched against registered Router, then we assign it to $routeToBeMatched
variable, we can procees it. What if the “redirect route equals current route” ? We can check it under if.
if ($routeToBeMatched = $this->getServiceLocator()->get('Router')->match($request)) { // handle if redirect route = current route $currentRouteMatchName = $this->getEvent()->getRouteMatch()->getMatchedRouteName(); if ($routeToBeMatched->getMatchedRouteName() != $currentRouteMatchName) { return $this->redirect()->toUrl($redirect); } }
Great! now, handle default redirection when doesnt’ match :
if ($routeToBeMatched = $this->getServiceLocator()->get('Router')->match($request)) { // handle if redirect route = current route $currentRouteMatchName = $this->getEvent()->getRouteMatch()->getMatchedRouteName(); if ($routeToBeMatched->getMatchedRouteName() != $currentRouteMatchName) { return $this->redirect()->toUrl($redirect); } } return $this->redirect()->toUrl('/user');
Ok, this is the complete code sample:
$redirect = $this->params()->fromQuery('redirect',''); $request = $this->getRequest(); $request->setUri($redirect); if ($routeToBeMatched = $this->getServiceLocator()->get('Router')->match($request)) { // handle if redirect route = current route $currentRouteMatchName = $this->getEvent()->getRouteMatch()->getMatchedRouteName(); if ($routeToBeMatched->getMatchedRouteName() != $currentRouteMatchName) { return $this->redirect()->toRoute($redirect); } } return $this->redirect()->toUrl('/user');
Update: There is a module for that that I created, go grab it here: https://github.com/samsonasik/RedirectHandlerModule 😉
Good way to ensure the user is not redirected outside the application.
I have to confess I don’t usually check this. I’ll probably do it from now on.
Well done!
Thanks so much. it helped