【CakePHP2.x】Securityコンポーネントを使用したときの不具合【black-holed】
開発チームの長谷です。
CakePHPでログイン機能を実装するため、Securityコンポーネントを使用していたら、
こんな謎のエラーが発生しました。
The request has been black-holed
ブラックホール?なんだこれは。。
特にフォーム送信後にブラウザで「戻る」をして、もう一回送信したりすると発生する。。。
まだペーペーの自分にはこのエラーがどういったものか分からなかったので、
とりあえず解決方法を調べてみることにしました。
PostやAjaxを許可する
フォーム画面でほぼほぼエラーが出ていたので、
beforeFilterでPostとついでにAjaxを許可するようにしました。
app/Controller/AppController.php
public function beforeFilter() { $this->Security->validatePost = false; $this->Security->csrfCheck = false; ... // ~なんらかの処理~ }
これでエラーが発生しなくなったかなと少し期待しつつ確認をしましたが
やっぱり、同じエラーが発生していた。
再び調査開始。
オーバーライドしているのを修正
AppController.phpのbeforeFilterでPostとAjaxを許可したことによって、
ControllerがbeforeFilterをオーバーライドしてしまい、
通信の許可がなくなってしまったらしい。
なので、black-holeエラーが発生するControllerを修正。
beforefilterにparent::beforeFilter();を追加します。
app/Controller/UserController.php
public function beforeFilter() { parent::beforeFilter(); // ~なんらかの処理~ }
これでエラーが出なくなっただろうと思い、
確認してみましたが、再度同じエラーが発生。。
ブラックホールコールバックの処理
ここまできて何だが、公式サイトに対応方法が書いてありました。。
Security コンポーネントによって制限されている時、 デフォルトでは、不正なリクエストとして 400 エラーを返し破棄します。
コントローラ中のコールバック関数を $this->Security->blackHoleCallback に設定することによってこの振る舞いを変更できます。
つまり、フォーム送信後にブラウザで「戻る」をしてもう一度送信をするという行為が
不正なリクエストなので、
400エラーを返しblack-holedエラーが発生していたということになります。
最初から公式サイトを見ておけばよかった。。
というわけで、black-holeエラーが発生するControllerのbeforefilterを以下のように修正。
public function beforeFilter() { parent::beforeFilter(); $this->Security->blackHoleCallback = 'blackhole'; $this->Security->validatePost = false; $this->Security->csrfCheck = false; // ~なんらかの処理~ } // ブラックホールをスルーする public function blackhole($type) { }
これで、black-holedエラーが出なくなりました!!
一安心。。
参考
https://book.cakephp.org/2.0/ja/core-libraries/components/security-component.html
http://www.aipacommander.com/entry/2015/04/27/180000