CakePHPでSSLを使ったサイトを構築したときにSecurityコンポーネントが上手くいかなく、更にはredirectメソッドがでトラブった状況をメモがてら下記に明記しておきます。同じ苦労をした方は参考になればと思います。
環境・条件
今回、苦戦した環境は以下の通りです。
- サーバー
- さくらインターネット 共有サーバー
- SSL
- あり
- スクリプト
- PHP
- PHPフレームワーク
- CakePHP Ver.2
- CakePHPで利用しているコンポーネント
- Auth、Security、他
他にも環境や条件がありますが、今回の内容には関係ないので割愛します。
無限ループとブラックホール
このシステムはAuthを利用してログインを行い、各データを登録・編集を行う一般的なデータ登録システムです。
今回、SSLを利用することによりCakePHPのSecurityコンポーネントを利用して各ページを強制的にSSL化するようにしました。このため、AppController.phpにAuthとSecurityのコンポーネントを下記のようにセットし、プログラムを書きました。
<?php
App::uses('Controller', 'Controller');
class AppController extends Controller {
public $components = array(
'Auth',
'Security',
);
public function beforeFilter() {
$this->Security->blackHoleCallback = 'forceSSL';
$this->Security->requireSecure();
}
public function forceSSL() {
return $this->redirect('https://'.env('SERVER_NAME').$this->here);
}
}
>
しかし、これでサイトを開くと無限ループになってしまうようで、ブラウザのFirefoxではしばらく経った後に「ページの自動転送設定が正しくありません」と表示されてしまします。試しに「$this->Security->blackHoleCallback = ‘forceSSL’」をコメントアウトすると
The request has been black-holed
Error: The requested address ‘/’ was not found on this server.
と、「ブラックホール」という何とも恐ろしい単語が表示されてどうにもなりません。
リダイレクトのurlメソッドが!
そこでいろいろと調べてみたところ、さくらインターネットのSSLでは「HTTPS」ではなく「HTTP_X_SAKURA_FORWARDED_FOR」でIPアドレスを吐き出すようです。試しに
var_dump($_SERVER);
で確認すると確かに「HTTP_X_SAKURA_FORWARDED_FOR」があります。これにより「/lib/Cake/Network/CakeRequest.php」を
protected $_detectors = array(
// 'ssl' => array('env' => 'HTTPS', 'value' => 1),
'ssl' => array('env' => 'HTTP_X_SAKURA_FORWARDED_FOR', 'pattern' => '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/'),
);
とする必要があります。
CakePHP(2.x)のSecurityComponentをさくらの共有SSLに対応させる – Qiita
さて、これでOKだろうとサイトを開くと良いところはいいのですが、入力フォームでデータを登録した後、なぜか強制的にログインページへ移動し、「$this->Auth->authError」で設定した「あなたはログインしていません」と表示されてしまします。
この原因がわからなくて半日以上かかって原因がわかりました。ログインページに飛ばしていたのはデータを保存した後に一覧ページなどへジャンプするリダイレクトメソッド「Controller::redirect()」でした。
このリダイレクトではコントローラやアクションをセットして指定のページに移動するのですが、その際、リダイレクトメソッドのある「/lib/Cake/Controller/Controller.php」を調べたところurlメソッド「Router::url()」でURLが「https」ではなく「http」のままになっていました。
そこで、こちらのページを参考に「/app/Config/routes.php」ファイルに
Router::fullBaseUrl('https://(ドメイン名)');
を明記することで何とかクリアすることができました。
文章にするとこれだけですが、これだけを見つけるのにはあっちを見たり、こっちを見たりでなかなか苦労した一日でした。(´Д`)はぁ~
もしかしたら、いろいろと試行錯誤したために、無駄な処理があるかもしれません。先にも書いたとおり何かしらの参考になればと思います。多分、一番参考になるのは未来の私じゃないでしょうか(笑)