![](/img/trans.png)
[英]Symfony4: The CSRF token is invalid. Please try to resubmit the form
[英]The CSRF token is invalid. Please try to resubmit the form
每次尝试提交表单时,我都会收到此错误消息:
CSRF 令牌无效。 请尝试重新提交表格
我的表单代码是这样的:
<form novalidate action="{{path('signup_index')}}" method="post" {{form_enctype(form)}} role="form" class="form-horizontal">
<div class="form-group">
{{ form_label(form.email, 'Email', {'label_attr': {'class': 'col-md-1 control-label'}}) }}
{{ form_widget(form.email, {'attr': {'class': 'col-md-2'}}) }}
{{ form_errors(form.email) }}
</div>
<div class="form-group">
{{ form_label(form.nickname, 'Nickname', {'label_attr': {'class': 'col-md-1 control-label'}}) }}
{{ form_widget(form.nickname, {'attr':{'class': 'col-md-2'}}) }}
{{ form_errors(form.nickname, {'attr': {'class': 'col-md-3'}}) }}
</div>
<div class="form-group">
{{ form_label(form.password, 'password', {'label_attr': {'class': 'col-md-1 control-label'}}) }}
{{ form_widget(form.password, {'attr': {'class': 'col-md-2'}}) }}
{{ form_errors(form.password, {'attr': {'class': 'col-md-3'}}) }}
</div>
<div class="form-group">
{{ form_label(form.password_repeat, 'Repeat password', {'label_attr': {'class': 'col-md-1 control-label'}}) }}
{{ form_widget(form.password_repeat, {'attr':{'class': 'col-md-2'}}) }}
{{ form_errors(form.password_repeat, {'attr': {'class': 'col-md-3'}}) }}
</div>
<div class="form-group">
<div class="col-md-1 control-label">
<input type="submit" value="submit">
</div>
</div>
</form>
有任何想法吗?
您需要在表单中添加_token
,即
{{ form_row(form._token) }}
截至目前,您的表单缺少 CSRF 令牌字段。 如果您使用 twig 表单函数来呈现表单,例如form(form)
这将自动为您呈现 CSRF 令牌字段,但您的代码显示您正在使用原始 HTML 呈现表单,例如<form></form>
,因此您必须手动渲染该字段。
或者,只需在{{ form_rest(form) }}
的结束标记之前添加{{ form_rest(form) }}
。
根据文档
这将呈现尚未为给定表单呈现的所有字段。 始终将它放在表单中的某个地方是个好主意,因为它会为您呈现隐藏字段并使您忘记呈现的任何字段更加明显(因为它会为您呈现该字段)。
当您的表单有很多元素时,您也可以看到此错误消息。
php.ini 中的这个选项导致问题
; How many GET/POST/COOKIE input variables may be accepted
max_input_vars = 1000
问题是 _token 字段未命中 PUT (GET) 请求,因此您必须增加值。
此外,它涉及一个大文件。 增加
upload_max_filesize
选项将解决问题。
发生这种情况是因为表单默认包含 CSRF 保护,这在某些情况下是不必要的。
您可以在getDefaultOptions
方法中的表单类中禁用此 CSRF 保护,如下所示:
// Other methods omitted
public function getDefaultOptions(array $options)
{
return array(
'csrf_protection' => false,
// Rest of options omitted
);
}
如果您不想禁用 CSRF 保护,则需要在表单中呈现 CSRF 保护字段。 可以通过在视图文件中使用{{ form_rest(form) }}
来完成,如下所示:
<form novalidate action="{{path('signup_index')}}" method="post" {{form_enctype(form)}} role="form" class="form-horizontal">
<!-- Code omitted -->
<div class="form-group">
<div class="col-md-1 control-label">
<input type="submit" value="submit">
</div>
</div>
{{ form_rest(form) }}
</form>
{{ form_rest(form) }}
呈现您尚未手动输入的所有字段。
在你的</form>
标签之前:
{{ form_rest(form) }}
它会自动插入其他重要的(隐藏的)输入。
我遇到了一个奇怪行为的问题:清除浏览器缓存并没有解决它,但清除 cookie(即 PHP 会话 ID cookie)确实解决了这个问题。
这有你检查了所有其他的答案后,包括验证你有一个隐藏的表单输入字段的令牌来完成。
除了其他人的建议之外,如果您的会话存储不工作,您可能会收到 CSRF 令牌错误。
在最近的一个案例中,我的一位同事将“session_prefix”更改为一个包含空格的值。
session_prefix: 'My Website'
这破坏了会话存储,这反过来意味着我的表单无法从会话中获取 CSRF 令牌。
如果您已将表单从纯 HTML 转换为 twig,请确保您没有遗漏删除结束</form>
标记。 愚蠢的错误,但正如我发现的那样,这可能是导致此问题的原因。
当我遇到这个错误时,一开始我无法弄清楚。 我正在使用form_start()
和form_end()
来生成表单,因此我不必使用form_row(form._token)
显式添加令牌,或者使用form_rest()
来获取它。 它应该已经由form_end()
自动添加。
问题是,我正在使用的视图是我从纯 HTML 转换为 twig 的视图,并且我错过了删除结束</form>
标记,因此而不是:
{{ form_end(form) }}
我有:
</form>
{{ form_end(form) }}
这实际上看起来可能会引发错误,但显然不会,因此当form_end()
输出form_rest()
,表单已经关闭。 表单实际生成的页面源码是这样的:
<form>
<!-- all my form fields... -->
</form>
<input type="hidden" id="item__token" name="item[_token]" value="SQAOs1xIAL8REI0evGMjOsatLbo6uDzqBjVFfyD0PE4" />
</form>
显然,解决方案是删除多余的结束标签,然后再喝一些咖啡。
我最近有这个错误。 原来我的 cookie 设置在 config.yml 中不正确。 将cookie_path
和cookie_domain
设置添加到framework.session
修复了它。
我最近遇到了同样的问题,我的案例在这里还没有提到:
问题是我在localhost
域上测试它。 我不确定为什么这是一个问题,但是在我将localhost
的主机名别名添加到/etc/hosts
后它开始工作,如下所示:
127.0.0.1 foobar
使用 Apache 和localhost
作为域时,会话可能有问题。 如果有人可以在评论中详细说明,我很乐意编辑此答案以包含更多详细信息。
如果您不想使用 form_row 或 form_rest 而只想访问 twig 模板中 _token 的值。 使用以下内容:
<input type="hidden" name="form[_token]" value="{{ form._token.vars.value }}" />
就我而言,实体中的 maxSize 注释出现问题,因此我将其从 2048 增加到 20048。
/**
* @Assert\File(
* maxSize = "20048k",
* mimeTypes = {"application/pdf", "application/x-pdf"},
* mimeTypesMessage = "Please upload a valid PDF"
* )
*/
private $file;
希望这个答案有帮助!
我遇到了类似的问题。 在确保实际呈现令牌字段后(请参阅接受的答案),我检查了我的 cookie。 我的 Chrome 浏览器中有 2(!)个域的 cookie,显然是因为我在与另一个应用程序相同的域上运行该应用程序,但使用不同的端口(即 mydomain.com 在有问题的应用程序运行时设置了原始 cookie在 mydomain.com:123) 现在显然 Chrome 发送了错误的 cookie,因此 CSRF 保护无法将令牌链接到正确的会话。
修复:清除相关域的所有 cookie,确保您没有在具有不同端口的同一域上运行多个应用程序。
我有同样的错误,但就我而言,问题是我的应用程序使用了多个一级域,而 cookie 使用了一个。 从config.yml
framework.session
中删除cookie_domain: ".%domain%"
导致 cookie 默认为表单所在的任何域,这解决了问题。
您需要记住 CSRF 令牌存储在会话中,因此由于会话处理无效,也会出现此问题。 如果您在 localhost 上工作,请检查例如会话 cookie 域是否设置正确(在 PHP 中,在 localhost 上它应该是空的)。
这在使用引导程序时似乎是一个问题,除非您通过 {{ form(form)}} 呈现表单。 此外,问题似乎只发生在 input type="hidden" 上。 如果您使用表单检查页面,您会发现隐藏的输入根本不是标记的一部分,或者它正在呈现但由于某种原因未提交。 如上所述,添加 {{form_rest(form)}} 或像下面这样包装输入应该可以解决问题。
<div class="form-group">
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
</div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.