CSRF令牌无效。请尝试重新提交表单

时间:2014-05-04 11:38:16

标签: php symfony twig

每次我尝试提交表单时都会收到此错误消息:

  

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>

有什么想法吗?

15 个答案:

答案 0 :(得分:81)

您需要在表单中添加_token,即

{{ form_row(form._token) }}

截至目前,您的表单缺少CSRF令牌字段。如果您使用twig表单函数来呈现类似form(form)的表单,这将自动为您呈现CSRF令牌字段,但您的代码显示您使用原始HTML(如<form></form>)呈现表单,因此您拥有手动渲染字段。

或者,只需在表单的结束标记之前添加{{ form_rest(form) }}

  

根据文件

     

这将呈现尚未针对给定呈现的所有字段   形成。总是把这个放在你的表格中的某个地方是个好主意   因为它会为你渲染隐藏的字段并使你忘记的任何字段   渲染更明显(因为它会为你渲染场)。

form_rest(view, variables)

答案 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_pathcookie_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>