Laravel5では全てのPOSTに勝手にCSRFチェックが付いてきます。
サイト内に置く通常のフォームには便利なのですが、Laravel外からのPOSTを受け取りたいときにも自動発動するため大迷惑です。
CSRFチェックを排除する方法が何故かなかなか見当たらなかったので調査結果を記載。
Kernel
デフォルトで適用されるミドルウェアは
app/Http/Kernel.php
に記載されています。
'App\Http\Middleware\VerifyCsrfToken'
が書かれている行を削除するとCSRFチェックが無効化されます。
この場合、あらゆるフォームに対してCSRFチェックが無くなります。
特定のフォームに対して有効にしたい場合、コントローラのコンストラクタに
$this->middleware('App\Http\Middleware\VerifyCsrfToken');
と書けば、そのコントローラでは有効になります。
しかし、各メソッド内に書いても効かないようです。
つまり、同一コントローラ内のフォームAには有効に、フォームBには無効にしたいといったことができません。
さらにデフォルトが危険側に倒れるため、この設定は微妙。
VerifyCsrfToken
CSRFチェックの本体は
app/Http/Middleware/VerifyCsrfToken.php
です。
ここにCSRFチェックを無効にしたいフォームを記載することでどうにかします。
デフォルトのVerifyCsrfToken::handle()は
public function handle($request, Closure $next){
return parent::handle($request, $next);
}
とだけ書かれていましたが、ここを変更。
// CSRFを除外したいURLリスト
protected $routes = [
'hoge/fuga',
'foo/bar',
'baz/qux',
];
// handleを変更
public function handle($request, Closure $next){
if($this->excludedRoutes($request)){
return $this->addCookieToResponse($request, $next($request));
}
return parent::handle($request, $next);
}
/*
* CSRFを除外したいURLであるかどうかをチェックする。
* @param Request リクエスト
* @return boolean CSRFを除外したいURLであればtrue
**/
protected function excludedRoutes($request){
foreach($this->routes as $route){
if ($request->is($route)){ return true; }
}
}
これで特定URLだけCSRFチェックを外すことができました。
一部のフォームを操作したいだけなのに、いちいち全体に影響のあるファイルを変更しないといけないのが微妙。
コントローラ
HogeController::postForm(){
$this->disableMiddleware('App\Http\Middleware\VerifyCsrfToken');
}
みたいなことはできんのか?
参考
http://laravel.io/forum/11-14-2014-disabling-the-csrf-middleware-in-laravel-5
http://www.camroncade.com/disable-csrf-for-specific-routes-laravel-5/
http://www.techigniter.in/tutorials/disable-csrf-check-on-specific-routes-in-laravel-5/