繁体   English   中英

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

[英]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) }}

根据文档

这将呈现尚未为给定表单呈现的所有字段。 始终将它放在表单中的某个地方是个好主意,因为它会为您呈现隐藏字段并使您忘记呈现的任何字段更加明显(因为它会为您呈现该字段)。

form_rest(视图,变量)

当您的表单有很多元素时,您也可以看到此错误消息。

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_pathcookie_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM