将 CSRF TOKEN 参数添加到 symfony 路由
Add CSRF TOKEN param to symfony routes
我的 routes.yml
中有一些路线
# Home page
adminHomePage:
path: /admin
defaults: { _controller: Themes\Controllers\DashboardController::indexAction }
loginRoutes:
resource: "routing/login.yml"
..........and so on..
我需要 "append" 所有路由 CSRF TOKEN 参数 ( key/CSRF_TOKEN )。
所以我的常规路线如下:
http://example.com/admin
应该是
http://example.com/admin/key/CSRF_TOKEN
但是我不想编辑我的 yml 文件,所以我想我需要覆盖一些 php class.
Like Magento do, add secret key to URL for CSRF (Cross-site request forgery) Attack Prevention.
你能帮忙吗?
谢谢
可能这不是一个好的决定,但它很快并且应该有效。
您可以编写自定义 UrlGenerator
将令牌附加到 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;
}
}
和 UrlMatcher
将从 urls
中删除令牌
namespace nnn;
class RedirectableUrlMatcher extends \Silex\RedirectableUrlMatcher
{
protected function matchCollection($pathinfo, \Symfony\Component\Routing\RouteCollection $routes)
{
$pathinfo = preg_replace('~/key/.+?(/|$)~', '', $pathinfo);
if ($pathinfo == '') $pathinfo = '/';
return parent::matchCollection($pathinfo, $routes);
}
}
并配置应用程序
$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();
令牌将在控制器中通过 $app['request']->get('_csrfToken')
访问
我的 routes.yml
中有一些路线 # Home page
adminHomePage:
path: /admin
defaults: { _controller: Themes\Controllers\DashboardController::indexAction }
loginRoutes:
resource: "routing/login.yml"
..........and so on..
我需要 "append" 所有路由 CSRF TOKEN 参数 ( key/CSRF_TOKEN )。 所以我的常规路线如下:
http://example.com/admin
应该是
http://example.com/admin/key/CSRF_TOKEN
但是我不想编辑我的 yml 文件,所以我想我需要覆盖一些 php class.
Like Magento do, add secret key to URL for CSRF (Cross-site request forgery) Attack Prevention.
你能帮忙吗?
谢谢
可能这不是一个好的决定,但它很快并且应该有效。
您可以编写自定义 UrlGenerator
将令牌附加到 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;
}
}
和 UrlMatcher
将从 urls
namespace nnn;
class RedirectableUrlMatcher extends \Silex\RedirectableUrlMatcher
{
protected function matchCollection($pathinfo, \Symfony\Component\Routing\RouteCollection $routes)
{
$pathinfo = preg_replace('~/key/.+?(/|$)~', '', $pathinfo);
if ($pathinfo == '') $pathinfo = '/';
return parent::matchCollection($pathinfo, $routes);
}
}
并配置应用程序
$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();
令牌将在控制器中通过 $app['request']->get('_csrfToken')