SslRequirementComponent の実装
Ruby on Rails には SSLRequirement というプラグインがある。これはあるコントローラにおける各アクションが、http または https のいずれでアクセスするべきか指定できる便利なプラグインである。CakePHP にも同様のプラグインがあるかもしれないが、勉強をかねて、自力で同様のコンポーネントを実装してみた。名付けて SslRequirementComponent。
使い方
このエントリの最後にあるソースコードを ssl_requirement.php という名前で app/controllers/components に保存する。(ssl_requirement_component.php という名前じゃないからね!!)そして、コントローラの中から
<?php class UsersController extends AppController { var $components = array('SslRequirement'); var $ssl_required_actions = array('login', 'signup'); var $ssl_allowed_actions = array('my_messages'); function login() { ... } function signup() { ... } function my_messages() { ... } function index() { ... } }
のように書く。
アクションへのアクセスが、指定されたとおり http または https プロトコルで行われることを保障する。このコンポーネントがロードされたコントローラでは、原則として、リクエストは http でアクセスされる。(何も指定がなければ、https アクセスは同一 URL に対する http アクセスへリダイレクトされる)
コントローラのメンバ変数 $ssl_required_actions と $ssl_allowed_actions にそれぞれ、
を記述することができる。
これだけで、login, signup アクションに関しては、必ず https でアクセスされることが保障される。my_messages アクションは http/https どちらでもよい。index アクションに関しては何の指定もないので、かならず http アクセスされる。
ソースコード
<?php class SslRequirementComponent extends Object { var $components = array('RequestHandler'); var $controller; function initialize(&$controller) { $this->controller = $controller; $this->ensureProperProtocol(); } // https リクエスト以外を受け付けないか? function isSSLRequired() { if(isset($this->controller->ssl_required_actions)) { return in_array($this->controller->action, $this->controller->ssl_required_actions); } else { return false; } } // https リクエストを許容するか? function isSSLAllowed() { if(isset($this->controller->ssl_allowed_actions)) { return in_array($this->controller->action, $this->controller->ssl_allowed_actions); } else { return false; } } function ensureProperProtocol() { if($this->isSSLAllowed()) { return; } if($this->isSSLRequired() && !$this->RequestHandler->isSSL()) { $url = 'https://' . $_SERVER['HTTP_HOST'] . $this->controller->here; // 第3パラメータを true にすることで、この場で処理を終了して、レスポンスを返す。 $this->controller->redirect($url, null, true); } elseif($this->RequestHandler->isSSL() && !$this->isSSLRequired()) { $url = 'http://' . $_SERVER['HTTP_HOST'] . $this->controller->here; $this->controller->redirect($url, null, true); } } }