【新卒 / 中途採用】サーバー / クラウドエンジニア 募集中!【大阪】

【新卒 / 中途採用】サーバー / クラウドエンジニア 募集中!【大阪】

【導入実績300社以上】AWS 構築・運用保守サービス

【導入実績300社以上】AWS 構築・運用保守サービス

【ECサイト構築】Shopify カスタムアプリ開発サービス

【ECサイト構築】Shopify カスタムアプリ開発サービス

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【音声アプリ開発】Twilio アプリ開発サービス

【音声アプリ開発】Twilio アプリ開発サービス

【システム開発サービス】SAKARAKU Lab(セカラクラボ)| Webシステム開発

【システム開発サービス】SAKARAKU Lab(セカラクラボ)| Webシステム開発

【取材記事】サーバー系企業ビヨンドが サーバーサイドエンジニアを募集中

【取材記事】サーバー系企業ビヨンドが サーバーサイドエンジニアを募集中

【対談記事】「やっぱクラウド移設っていいですよね」マイネット × ビヨンド エンジニア対談

【対談記事】「やっぱクラウド移設っていいですよね」マイネット × ビヨンド エンジニア対談

ビヨンド公式YouTubeチャンネル「びよまるチャンネル」

ビヨンド公式YouTubeチャンネル「びよまるチャンネル」

【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


この記事をかいた人

About the author

長谷竜弥

入社4年目です。
システム部に所属しています。
ずっと大阪で勤務していましたが、2019年の11月から横浜開発室に異動になりました。
趣味は野球で休日は草野球をしていましたが、横浜に来てからはできておらず悶々と日々を過ごしております。