Welcome to Abdul Malik Ikhsan's Blog

Zend Framework 2 : Check request URI matched against registered Router

Posted in Tutorial PHP, Zend Framework 2 by samsonasik on December 28, 2014

zf2-zendframework2 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 😉

Advertisements

3 Responses

Subscribe to comments with RSS.

  1. Alejandro Celaya said, on December 28, 2014 at 7:58 pm

    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.

  2. Witold Wasiczko said, on December 30, 2014 at 4:56 pm

    Well done!

  3. Cyrilb said, on October 30, 2016 at 4:43 pm

    Thanks so much. it helped


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: