每次我尝试提交表单时都会收到此错误消息:
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>
有什么想法吗?
答案 0 :(得分:81)
您需要在表单中添加_token
,即
{{ form_row(form._token) }}
截至目前,您的表单缺少CSRF令牌字段。如果您使用twig表单函数来呈现类似form(form)
的表单,这将自动为您呈现CSRF令牌字段,但您的代码显示您使用原始HTML(如<form></form>
)呈现表单,因此您拥有手动渲染字段。
或者,只需在表单的结束标记之前添加{{ form_rest(form) }}
。
根据文件
这将呈现尚未针对给定呈现的所有字段 形成。总是把这个放在你的表格中的某个地方是个好主意 因为它会为你渲染隐藏的字段并使你忘记的任何字段 渲染更明显(因为它会为你渲染场)。
答案 1 :(得分:23)
如果您的表单包含大量元素,也可以看到此错误消息。
php.ini中的此选项导致问题
; How many GET/POST/COOKIE input variables may be accepted
max_input_vars = 1000
问题是_token错过了PUT(GET)请求 所以,你可以增加价值。
此外,它涉及一个大文件。增加
upload_max_filesize
选项将解决问题
答案 2 :(得分:9)
这是因为默认情况下表单包含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) }}
会呈现您尚未手动输入的所有字段。
答案 3 :(得分:5)
在</form>
代码放置之前:
{{ form_rest(form) }}
它会自动插入其他重要(隐藏)输入。
答案 4 :(得分:2)
除了其他人的建议,如果您的会话存储无效,您可能会收到CSRF令牌错误。
在最近的一个案例中,我的一位同事将'session_prefix'更改为其中有空格的值。
session_prefix: 'My Website'
这破坏了会话存储,这反过来意味着我的表单无法从会话中获取CSRF令牌。
答案 5 :(得分:2)
我遇到了一个奇怪的问题:清除浏览器缓存没有修复它,但清除cookie(即PHP会话ID cookie)确实解决了这个问题。
必须在之后完成检查所有其他答案,包括验证您做在隐藏表单输入字段中有令牌。
答案 6 :(得分:2)
我最近遇到了这个错误。事实证明我的cookie设置在config.yml中是不正确的。将cookie_path
和cookie_domain
设置添加到framework.session
修复了它。
答案 7 :(得分:1)
我最近遇到了同样的问题,而我的案子在这里还没有提到:
问题是我正在SELECT e.entity_id,
MAX(e.occurred_at) FILTER (WHERE type = 'created') as created_at,
MAX(e.occurred_at) FILTER (WHERE type = 'completed') AS completed_at,
MAX(e.occurred_at) FILTER (WHERE type = 'failed') AS failed_at
FROM events e
GROUP BY e.entity_id;
域上对其进行测试。我不确定为什么这确实是个问题,但是在我将localhost
的主机名别名添加到localhost
中之后,它开始起作用了:
/etc/hosts
在使用Apache和127.0.0.1 foobar
作为域时,会话可能有问题。如果有人可以在评论中详细说明,我很乐意编辑此答案以包括更多详细信息。
答案 8 :(得分:0)
如果您不想使用form_row或form_rest,只想在twig模板中访问_token的值。使用以下内容:
<input type="hidden" name="form[_token]" value="{{ form._token.vars.value }}" />
答案 9 :(得分:0)
在我的情况下,我在实体中遇到了maxSize注释的问题,所以我将它从2048增加到20048。
/**
* @Assert\File(
* maxSize = "20048k",
* mimeTypes = {"application/pdf", "application/x-pdf"},
* mimeTypesMessage = "Please upload a valid PDF"
* )
*/
private $file;
希望这个答案有所帮助!
答案 10 :(得分:0)
如果您已将表单从纯HTML转换为twig,请确保您没有错过删除结束</form>
标记。愚蠢的错误,但正如我发现它可能导致这个问题。
当我收到此错误时,我一开始无法弄明白。我使用form_start()
和form_end()
来生成表单,因此我不必使用form_row(form._token)
明确添加令牌,或者使用form_rest()
来获取它。 It should have already been added automatically by 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>
显然,解决方案是删除额外的结束标签,并可能再喝一些咖啡。
答案 11 :(得分:0)
我遇到了类似的问题。确保实际呈现令牌字段后(请参阅接受的答案)我检查了我的cookie。 在我的Chrome浏览器中有两个(!)Cookie用于域名,显然是因为我在同一个域上运行该应用程序而不是另一个应用程序,但使用不同的端口(即mydomain.com在运行有错误的应用程序时设置原始cookie在mydomain.com:123) 现在显然Chrome发送了错误的cookie,因此CSRF保护无法将令牌链接到正确的会话。
修复:清除相关域的所有Cookie,确保您不要在具有不同端口的同一域上运行多个应用程序。
答案 12 :(得分:0)
我有同样的错误,但在我的情况下,问题是我的应用程序使用多个第一级域,而cookie使用一个。从cookie_domain: ".%domain%"
中的framework.session
中删除config.yml
导致Cookie默认为表单所在的任何域,并解决了问题。
答案 13 :(得分:0)
您需要记住,CSRF令牌存储在会话中,因此由于无效的会话处理,也会发生此问题。如果您使用的是本地主机,请检查例如如果会话cookie域设置正确(在php中,在localhost上应为空)。
答案 14 :(得分:-1)
除非您通过{{form(form)}}呈现表单,否则在使用引导程序时这似乎是一个问题。此外,问题似乎只发生在输入类型=&#34;隐藏&#34;。如果您使用表单检查页面,您将发现隐藏的输入根本不是标记的一部分,或者它正在呈现但由于某种原因未提交。如上所述,添加{{form_rest(form)}}或包装输入如下所示应该可以解决问题。
<div class="form-group">
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
</div>