除非我在FormType
文件中将csrf_protection
参数切换为true,否则传递给每个表单的数据都会正确地添加到DB中。
CSRF令牌无效。请尝试重新提交表单。
为什么会发生这种情况?有人能告诉我应该如何修复这个问题吗?我正在使用Symfony助手创建表单,这意味着csrf令牌应该自动呈现。
我尝试使用form_row()
和form_widget()
函数分别呈现字段,但没有任何帮助。
注解类型.php
class CommentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('content', TextareaType::class)
->add('submit', SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Comment::class,
'csrf_protection' => true,
'csrf_field_name' => 'token',
'csrf_token_id' => 'comment_csrf_id'
]);
}
}
评论控制器.php
class CommentController extends AbstractController
{
private EntityManagerInterface $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* @Route("/comments", name="app_comments")
*/
public function indexAction(Request $request): Response
{
$user = $this->getUser();
$comment = new Comment();
$commentForm = $this->createForm(CommentType::class, $comment);
$commentForm->handleRequest($request);
if ($commentForm->isSubmitted() && $commentForm->isValid()) {
$this->addComment($comment, $user, $request->request->get('parent_id') ?? null);
$this->addFlash('success', 'Commentary added');
return $this->redirectToRoute('app_comments');
}
$allComments = $this->entityManager->getRepository(Comment::class)->findAll();
$sortedComments = $this->sortComments($allComments);
return $this->renderForm('comments/index.html.twig', [
'commentForm' => $commentForm,
'sortedComments' => $sortedComments,
]);
}
index.html.twig(具有父窗体的文件)
{% block body %}
<section class="gradient-custom">
<div class="container my-2 py-2">
<div class="row d-flex justify-content-center">
<div class="col-md-12 col-lg-10 col-xl-8 mb-4">
<div class="card">
<div class="card-body p-4">
<h3 class="text-center mb-4 pb-2">Tree Comments</h3>
<div class="row">
<div class="col">
{% for comment in sortedComments %}
{% set templateAttrs = [comment.getId, asset('avatars/avatar-6.webp'), asset('avatars/avatar-7.webp')] %}
{% include 'comments/comment.html.twig' with { comment: comment, commentIdValue: templateAttrs.0, userImage: templateAttrs.1} %}
{% for child in comment.children %}
<div class="mt-3 ml-5">
{% include 'comments/comment.html.twig' with { comment: child, commentIdValue: templateAttrs.0, userImage: templateAttrs.2} %}
</div>
{% endfor %}
<hr>
{% endfor %}
</div>
</div>
</div>
{% if app.user == true %}
{{ form_start(commentForm, {'attr': {'class': 'ml-4 mr-4 mb-4 pb-2'}}) }}
<div class="form-group">
{{ form_label(commentForm.content, 'Your Commentary') }}
<textarea class="form-control"
name="{{ field_name(commentForm.content) }}"
rows="2"
required>
</textarea>
{{ form_errors(commentForm.content) }}
</div>
<div class="submit">
<input class="btn btn-primary"
name="{{ field_name(commentForm.submit) }}"
type="submit"
value="Submit">
</div>
{{ form_end(commentForm) }}
{% endif %}
{% if app.user == false %}
<div class="text-center mb-2 pb-2">
<p>To leave your commentary, please <a href="{{ path('app_login') }}">log in</a></p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<script>
</script>
</section>
{% endblock %}
comment.html.twig(它有子窗体,并且此文件包含在index.html.twig中)
<div class="d-flex flex-start mb-1">
<a class="me-3" href="javascript:void(0)">
<img class="rounded-circle shadow-1-strong mr-2"
src="{{ userImage }}" alt="Random Image" width="65"
height="65"/>
</a>
<div class="flex-grow-1 flex-shrink-1">
<div class="col-11 p-0 d-inline-block comment">
<div class="d-flex justify-content-between align-items-center">
<p class="mb-1">
{{ comment.user.userIdentifier }}
<span class="small">- {{ comment.createdAt|ago }} </span>
</p>
</div>
<p class="small mb-0">
{% if comment.isDeleted == true %}
<i> *This commentary was deleted by moderator* </i>
{% else %}
{{ comment.content }}
{% endif %}
</p>
{% if is_granted('IS_AUTHENTICATED_FULLY') and comment.isDeleted == false %}
{% set isAlreadyLikedComment = '' %}
{% for like in comment.getCommentLikes %}
{% set isAlreadyLikedComment = like.user.getId %}
{% endfor %}
<div class="js-likes-unlikes">
<a href="{{ path('app_comment_like_unlike') }}"
id="comment-like"
data-entity-id="{{ comment.id }}"
data-csrf-token="{{ csrf_token('comment' ~ comment.id) }}"
data-liked="{{ isAlreadyLikedComment == app.user.id ? '1' : '0' }}"
data-likes-counter="{{ comment.commentLikes.count }}"
class="btn-like">
<i class="comment-like-{{ comment.id }}">
{{ isAlreadyLikedComment == app.user.id ? '♥' : '♡' }}
</i>
</a>
<span class="counter small mb-0"
id="count-likes-{{ comment.id }}">{{ comment.commentLikes.count }}</span>
</div>
</div>
<div class="col-1 p-0 float-right d-flex align-items-center flex-column">
<a href="javascript:void(0)"
onclick="document.getElementById('formreply-{{ comment.getId }}').style.display='';">
<span class="small">reply</span>
{% if is_granted('ROLE_ADMIN') %}
<a href="{{ path('delete_comment',{'id': comment.getId }) }}">
<span class="small"> delete</span>
</a>
{% endif %}
</a>
{% endif %}
</div>
</div>
</div>
{% set formAttrs = ['m2 pb-2', 'formreply-' ~ comment.getId, 'display: none !important;'] %}
{% if app.user == true %}
<div class="d-flex flex-column">
<div class="flex-grow-1 flex-shrink-1 reply-form">
{{ form_start(commentForm, {'attr': {'class': formAttrs.0, 'id': formAttrs.1, 'style': formAttrs.2 }}) }}
<div class="form-group">
{{ form_label(commentForm.content, 'Your Commentary') }}
<textarea class="form-control"
name="{{ field_name(commentForm.content) }}" required>@{{ comment.user.userIdentifier }}, </textarea>
{{ form_errors(commentForm.content) }}
</div>
<div class="submit">
<input class="btn btn-primary"
name="{{ field_name(commentForm.submit) }}"
type="submit"
value="Submit">
</div>
<input type="hidden"
name="parent_id"
value="{{ commentIdValue }}">
{{ form_end(commentForm) }}
</div>
{% endif %}
</div>
在这种情况下,可以将两个表单绑定到同一个实体吗?我也尝试创建两个formType
文件,但将它们绑定到同一个实体,这只起到了部分作用:父窗体正确提交,但子窗体保留错误:
CSRF令牌无效。请尝试重新提交表单。
2条答案
按热度按时间d8tt03nd1#
这可能与在同一页上呈现或处理表单的方式有关。要解决此问题,可以尝试以下步骤:
1.更新您的
CommentType.php
,使父窗体和子窗体都具有唯一的CSRF令牌:这将为每个表单示例生成唯一的CSRF令牌。
1.确保使用
form_row()
或form_widget()
函数呈现CSRF令牌,因为您提到您已经尝试过了,所以我假设这已经到位。1.进行以下更改后,请记住清除Symfony缓存:
告诉我有没有帮助。
oxcyiej72#
尝试为父窗体和子窗体生成唯一的CSRF标记ID。
评论控制器.php
更新您的Twig模板以使用新的表单示例
parentCommentForm
和childCommentForminstead of the previous single form instance
commentForm '。索引.html.小树枝
评论.html.twig