![](/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.