CakePHP

CakePHP(2.x)のSecurityComponentをさくらの共有SSLに対応させる

More than 3 years have passed since last update.


共有SSLでお手軽セキュア→失敗

とっても便利なSecurityComponent。以下のように記述すると、HTTP接続時、自動的にHTTPSへリダイレクトしてくれます。


HogesController

public function beforeFilter() {

$this->Security->blackHoleCallback = 'forceSSL';
$this->Security->requireSecure();
}

public function forceSSL() {
$this->redirect('https://'.env('SERVER_NAME').$this->here);
}


しかしさくらインターネットのレンタルサーバー環境では、SSLの判定に失敗します。

https付きでアクセスしても、SSLではないと判定されてリダイレクトループに。なんでや。


悪いのはどいつだ

SecurityComponent.phpを読んでみると、下記のようにsslの判定を行っていました。


/lib/Cake/Controller/Component/SecurityComponent.php

if (!$this->request->is('ssl')) {

if (!$this->blackHole($controller, 'secure')) {
return null;
}
}

試しにコメントアウトするとブラックホールに吸われなくなったので、このロジックを修正すれば良さそうです。

CakeRequestを読むと、\$_detectorsに\$_SERVER変数からの抽出条件が記載されています。


/lib/Cake/Network/CakeRequest.php

    protected $_detectors = array(

...
'ssl' => array('env' => 'HTTPS', 'value' => 1),
...
);

さくらの共有SSLでは、「HTTPS」の代わりに「HTTP_X_SAKURA_FORWARDED_FOR」としてIPアドレスを出力してくれます。

なのでこうしました。


/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]?)$/'),
...
);

正規表現でIPアドレス(v4)のパターンを記述しています。

ただ、接続環境によってはIPv6で返ってきたりするかもしれないので、ちょっと不安ですね。


コンポーネントを使わない方法

コントローラ中でSecurityコンポーネントを使用しないなら、手っ取り早くenv('PARAM')で判断するのが簡単です。


HogesController

public function beforeFilter() {

if(is_null(env('HTTP_X_SAKURA_FORWARDED_FOR'))) {
$this->redirect('https://'.env('SERVER_NAME').$this->here);
}
}