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

  • 14
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

共有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);
    }
}