为啥我的 CSRF 令牌在使用 Form::open() 时是空的?

Posted

技术标签:

【中文标题】为啥我的 CSRF 令牌在使用 Form::open() 时是空的?【英文标题】:Why is my CSRF token empty when using Form::open()?为什么我的 CSRF 令牌在使用 Form::open() 时是空的? 【发布时间】:2016-03-29 03:00:38 【问题描述】:

刚刚刚开始,所以请原谅我。我对 CodeIgniter 有扎实的了解,所以我明白发生了什么。但是,我注意到创建表单时我的 CSRF 令牌是空的。我正在通过 laracasts 视频来了解 Laravel 工作流程。

myfile.blade.php

 !! Form::open((array('action' => 'MyController@method'))) !!
    ...
 !! Form::close() !!

这是我查看源代码时得到的结果:

<form method="POST" action="http://mysite.dev/route" accept-charset="UTF-8">
<input name="_token" type="hidden">
</form>

我查看了配置目录,但没有看到必须启用 csrf。我需要更新其他设置吗?

感谢您的建议。

编辑

即使这给了我一个空的隐藏输入字段:

 Form::token()   // <input name="_token" type="hidden">

编辑

这是我的控制器的样子:

//use Illuminate\Http\Request;
use Request;
use App\Article;
use App\Http\Requests;
use App\Http\Controllers\Controller;


public function store(Request $request)

    $input = Request::all();

    return $input;

所以我更新后的表单标签如下所示:

!! Form::open((array('action' => 'ArticleController@store'))) !!
...

当我提交时,我可以看到 json 响应 - 令牌显然是空的。

"_token":"","title":"test","body":"test"

【问题讨论】:

看我的回答@damon 你使用的是哪个版本的 Laravel?另外,如果你在看 Laravel 基础系列,它有点过时了。 嗨,Thomas,看起来我使用的是 5.2.3。我正在学习“Laravel 5 Fundamentals”系列。 【参考方案1】:

Laravel 基础系列适用于 Laravel 5.0,因此您有几个选择。您可以安装 Laravel 5.0 以继续该系列。为了安装 L5.0,您需要运行以下命令:

composer create-project laravel/laravel directory "~5.0.0" --prefer-dist

如果你想使用 Laravel 5.2(我会推荐它,Jeffrey Way 很可能很快就会发布一个关于这个的系列),还有一些额外的事情需要考虑。

首先,将所有路由放入一个“网络”中间件组,如下所示:

Route::group(['middleware' => ['web']], function () 

    // Put your routes inside here

);

过去,默认情况下每个请求都会运行多个中间件。在 5.2 中,情况不再如此。例如,令牌存储在会话中,但在 5.2 中,不会自动应用“StartSession”中间件之类的东西。因此,需要将“网络”中间件应用于您的路由。 5.2这个改动的原因:

中间件组允许您将多个路由中间件分组到一个方便的键下,允许您一次将多个中间件分配给一个路由。例如,在同一应用程序中构建 Web UI 和 API 时,这可能很有用。您可以将会话和 CSRF 路由分组到 web 组中,也可以将速率限制器分组到 api 组中。

另外,在 Laravel 基础系列中,Jeffrey 引入了“illuminate/html”包,但现在,大多数人使用 laravel 集体包。他们处理许多从核心中取出的 Laravel 包。因此,我将删除“illuminate/html”包。在您的composer.json 文件中,删除"illuminate/html: 5.0"(或require 部分中的任何内容)。此外,删除相应的服务提供者并形成您添加到 config/app.php 文件中的外观。

要安装 laravel 集体版本,请将其添加到您的 composer.json 文件中:"laravelcollective/html": "5.2.*-dev"。然后,运行composer update。完成后,在您的 config/app.php 文件中,将其添加到您的 providers 数组中:

Collective\Html\HtmlServiceProvider::class,

并将其添加到您的别名数组中:

'Form' => Collective\Html\FormFacade::class,
'Html' => Collective\Html\HtmlFacade::class,

我希望我没有遗漏任何其他东西。

【讨论】:

非常感谢您的详细回答。 这似乎是答案,尽管我现在想知道... Route::group(['middleware' =&gt; ['web']], function () ... ...是否足够了。 是的,将其添加到您的路线可能就足够了,但最好使用 laravelcollective/html 而不是Illumination/html,因为它已被弃用并且会导致问题更进一步。同样值得注意的是 - 在将行添加到您的 app.php 之前通过作曲家对其进行更新,否则您将遇到错误。 它解决了这个问题,甚至 Laravel 5.1 不需要 'web' 中间件【参考方案2】:

这是一个配置问题。您需要将配置文件...config/app.php 中的应用程序密钥设置为 32 个字符的字符串或使用 artisan cli php artisan key:generate 生成密钥以便您能够使用 CSRF 令牌。

还要确保在 web 组路由中包含使用 CSRF 令牌的路由。

您可以通过在包含在默认 routes.php 文件中的 Web 中间件组之外定义它们的路由来排除 URI,或者通过将 URI 添加到 VerifyCsrfToken 中间件的 $except 属性:http://laravel.com/docs/5.2/routing#csrf-protection

【讨论】:

【参考方案3】:

如果您有一个登录页面,并且您想使用以下命令清除会话:

Session::flush();

不要忘记,这也会在将 csrf 令牌放入视图之前清除它

【讨论】:

【参考方案4】:

应该是

!! Form::open((array('action' => 'MyController@method')))  !!
    ...
 !! Form::close() !!

【讨论】:

嗨,亚当,感谢您的回复!我已更新您的建议以使用我的实际控制器方法,但我仍然得到同样的结果。没有价值的隐藏输入。这是我正在做(或不做)的事情造成的。我已经更新了我的问题以包含完整的控制器。也许有些东西我没有包括在内。【参考方案5】:

我已经解决了 HtmlService 提供者的问题,实际上 5.2 版本删除了 Illuminate 并添加了集体按照步骤解决问题:

    composer require laravelcollective/html composer update 在config/app.php中添加

'providers' => ['Collective\Html\HtmlServiceProvider'], 'aliases' => [ 'Form' => 'Collective\Html\FormFacade', 'Html' => 'Collective\Html\HtmlFacade', ],

然后您就可以使用该表单了。

【讨论】:

这很难阅读,因为它看起来都像代码。如果你能更好地格式化它,那会有所帮助。

以上是关于为啥我的 CSRF 令牌在使用 Form::open() 时是空的?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 spring 安全配置似乎拒绝了有效的 csrf 令牌

为啥恶意站点在攻击前无法通过 GET 获取 CSRF 令牌?

为啥我在 laravel 中运行测试时收到“CSRF 令牌不匹配”?

为啥 CSRF 令牌应该在元标记和 cookie 中?

如何在 Laravel 中禁用 CSRF 令牌以及为啥我们必须禁用它?

为啥 Express/Connect 会在每个请求上生成新的 CSRF 令牌?