将 Symfony Form 组件与 security-csrf 独立使用 - 提交时出错
Using Symfony Form component standalone with security-csrf - error on submission
我有一个关于 symfony/form
用作独立组件和 security-csrf
运行 PHP 内置服务器的问题。我几乎不记得 Symfony 框架有过这样的问题。
将 symfony/form
设置为独立组件时,我为 v4.2 和 v5.1 都尝试了此代码 https://github.com/xmgcoyi/standalone-forms/tree/4.2+twig. A rewrite of webmozart's example mentioned here https://symfony.com/doc/current/components/form.html
csrf 令牌是使用 twig-bridge 生成的,但是在提交表单时 - 在调用时出现 $form->isValid()
- invalid csrf
错误。
默认启用 csrf 保护,设置为 false
- 表单提交。
尝试使用 NativeSessionTokenStorage
和 SessionTokenStorage + Session of HttpFoundation
两种设置的 CSRF 组件。
你能给我一些提示,告诉我哪里做错了吗?
P.S.
提交时出现 csrf 错误的代码示例:
- https://github.com/xmgcoyi/standalone-forms/tree/4.2+twig
- https://github.com/liorchamla/pratique-symfony-form/tree/06-protection-csrf
UPD
上面的应用程序运行良好,问题出在充满垃圾的浏览器存储中。
在 $formFactory->createBuilder(FormType::class, null, ['csrf_protection' => false])
中设置为 false
提交表单
这是一个猜测,但 4.2 链接的 repo 有:
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);
$csrfTokenManager = new CsrfTokenManager();
两个令牌管理器。一个用于 twig 表单引擎,一个用于表单工厂扩展。这似乎不是一件合理的事情。
这是更新后的 5.1 工作示例。我从您的链接回购协议中进一步剥离了它。但我唯一真正改变的是令牌管理器。
# index.php
require_once '../vendor/autoload.php';
$app = new App();
$app->run();
final class App
{
public function run()
{
$csrfGenerator = new UriSafeTokenGenerator();
$csrfStorage = new NativeSessionTokenStorage();
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);
$twig = new Environment(new FilesystemLoader([
'../templates',
'../vendor/symfony/twig-bridge/Resources/views/Form',
]));
$formEngine = new TwigRendererEngine(['form_div_layout.html.twig'], $twig);
$twig->addRuntimeLoader(new FactoryRuntimeLoader([
FormRenderer::class => function () use ($formEngine,$csrfManager) {
return new FormRenderer($formEngine, $csrfManager);
},
]));
$twig->addExtension(new TranslationExtension());
$twig->addExtension(new FormExtension());
$formFactory = Forms::createFormFactoryBuilder()
->addExtension(new CsrfExtension($csrfManager))
//->addExtension(new ValidatorExtension($validator))
->getFormFactory();
$form = $formFactory->createBuilder()
->add('firstName', TextType::class)
->getForm();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$form->submit($_POST[$form->getName()]); // form
if ($form->isValid()) {
dump('form is valid');
}
}
echo $twig->render('index.html.twig', [
'form' => $form->createView(),
]);
}
}
composer.json就是:
{
"require": {
"symfony/form": "^5.1",
"symfony/twig-bridge": "^5.1",
"symfony/translation": "^5.1",
"symfony/security-csrf": "^5.1"
},
"require-dev": {
"symfony/var-dumper": "^5.1"
}
}
如果您仍然遇到问题,那么我建议您追踪会话的存储位置,然后验证是否正确存储了 csrf 令牌。它应该看起来像:
_csrf|a:1:{s:4:"form";s:43:"9v1tUNe3J3eYVOmEPwVdz5_iISfzBg8Qa9pLMV8tSN4";}
这实际上是一种将 twig 系统用于独立表单的有趣练习。谢谢
我有一个关于 symfony/form
用作独立组件和 security-csrf
运行 PHP 内置服务器的问题。我几乎不记得 Symfony 框架有过这样的问题。
将 symfony/form
设置为独立组件时,我为 v4.2 和 v5.1 都尝试了此代码 https://github.com/xmgcoyi/standalone-forms/tree/4.2+twig. A rewrite of webmozart's example mentioned here https://symfony.com/doc/current/components/form.html
csrf 令牌是使用 twig-bridge 生成的,但是在提交表单时 - 在调用时出现 $form->isValid()
- invalid csrf
错误。
默认启用 csrf 保护,设置为 false
- 表单提交。
尝试使用 NativeSessionTokenStorage
和 SessionTokenStorage + Session of HttpFoundation
两种设置的 CSRF 组件。
你能给我一些提示,告诉我哪里做错了吗?
P.S. 提交时出现 csrf 错误的代码示例:
- https://github.com/xmgcoyi/standalone-forms/tree/4.2+twig
- https://github.com/liorchamla/pratique-symfony-form/tree/06-protection-csrf
UPD 上面的应用程序运行良好,问题出在充满垃圾的浏览器存储中。
在 $formFactory->createBuilder(FormType::class, null, ['csrf_protection' => false])
中设置为 false
提交表单
这是一个猜测,但 4.2 链接的 repo 有:
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);
$csrfTokenManager = new CsrfTokenManager();
两个令牌管理器。一个用于 twig 表单引擎,一个用于表单工厂扩展。这似乎不是一件合理的事情。
这是更新后的 5.1 工作示例。我从您的链接回购协议中进一步剥离了它。但我唯一真正改变的是令牌管理器。
# index.php
require_once '../vendor/autoload.php';
$app = new App();
$app->run();
final class App
{
public function run()
{
$csrfGenerator = new UriSafeTokenGenerator();
$csrfStorage = new NativeSessionTokenStorage();
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);
$twig = new Environment(new FilesystemLoader([
'../templates',
'../vendor/symfony/twig-bridge/Resources/views/Form',
]));
$formEngine = new TwigRendererEngine(['form_div_layout.html.twig'], $twig);
$twig->addRuntimeLoader(new FactoryRuntimeLoader([
FormRenderer::class => function () use ($formEngine,$csrfManager) {
return new FormRenderer($formEngine, $csrfManager);
},
]));
$twig->addExtension(new TranslationExtension());
$twig->addExtension(new FormExtension());
$formFactory = Forms::createFormFactoryBuilder()
->addExtension(new CsrfExtension($csrfManager))
//->addExtension(new ValidatorExtension($validator))
->getFormFactory();
$form = $formFactory->createBuilder()
->add('firstName', TextType::class)
->getForm();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$form->submit($_POST[$form->getName()]); // form
if ($form->isValid()) {
dump('form is valid');
}
}
echo $twig->render('index.html.twig', [
'form' => $form->createView(),
]);
}
}
composer.json就是:
{
"require": {
"symfony/form": "^5.1",
"symfony/twig-bridge": "^5.1",
"symfony/translation": "^5.1",
"symfony/security-csrf": "^5.1"
},
"require-dev": {
"symfony/var-dumper": "^5.1"
}
}
如果您仍然遇到问题,那么我建议您追踪会话的存储位置,然后验证是否正确存储了 csrf 令牌。它应该看起来像:
_csrf|a:1:{s:4:"form";s:43:"9v1tUNe3J3eYVOmEPwVdz5_iISfzBg8Qa9pLMV8tSN4";}
这实际上是一种将 twig 系统用于独立表单的有趣练习。谢谢