Ste
Ste

Reputation: 1520

Add CSRF TOKEN param to symfony routes

i have some routes in my routes.yml

    # Home page
    adminHomePage:
         path:     /admin
         defaults: { _controller: Themes\Controllers\DashboardController::indexAction }
            loginRoutes:
                resource: "routing/login.yml"

..........and so on..

I need to "append" to all routes CSRF TOKEN param ( key/CSRF_TOKEN ). So my regular route look like:

http://example.com/admin

should be

http://example.com/admin/key/CSRF_TOKEN

But i do not want to edit my yml file, so i think i need to override some php class.

Like Magento do, add secret key to URL for CSRF (Cross-site request forgery) Attack Prevention.

Can you help?

Thanks

Upvotes: 0

Views: 851

Answers (1)

Max P.
Max P.

Reputation: 5679

May be it is not good decision, but it is fast and should work.
You can write custom UrlGenerator that will append token to urls

namespace nnn;

class UrlGenerator extends \Symfony\Component\Routing\Generator\UrlGenerator
{
    protected $csrfToken;

    protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, array $requiredSchemes = array())
    {
        $url = parent::doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);

        if (isset($this->csrfToken)) {
            $url = rtrim($url, '/') . '/key/' . $this->csrfToken;
        }

        return $url;
    }
}

and UrlMatcher that will cut token from urls

namespace nnn;

class RedirectableUrlMatcher extends \Silex\RedirectableUrlMatcher
{
    protected function matchCollection($pathinfo, \Symfony\Component\Routing\RouteCollection $routes)
    {
        $pathinfo = preg_replace('~/key/.+?(/|$)~', '$1', $pathinfo);
        if ($pathinfo == '') $pathinfo = '/';

        return parent::matchCollection($pathinfo, $routes);
    }
}

and configure application

$app['url_generator'] = $app->share(function ($app) {
    $app->flush();

    $urlGenerator = new \nnn\UrlGenerator($app['routes'], $app['request_context']);
    $urlGenerator->setCsrfToken('1234567890');

    return $urlGenerator;
});

$app['url_matcher'] = $app->share(function () use ($app) {
    return new \nnn\RedirectableUrlMatcher($app['routes'], $app['request_context']);
});

$app['dispatcher']->addListener(\Symfony\Component\HttpKernel\KernelEvents::REQUEST, function($event) use ($app) {
    $request = $event->getRequest();
    $path = $request->getPathInfo();
    if (\preg_match('~/key/(.+?)(?:/|$)~', $path, $matches)) {
        $request->attributes->set('_csrfToken', $matches[1]);
    }
}, 1024);

$app->run();

Token will be accessible in controllers through $app['request']->get('_csrfToken')

Upvotes: 1

Related Questions