CakePHP3を触ってみました 〜クッキー暗号化ミドルウェア〜

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
クッキーです。それ以上でもそれ以下でもない

この記事を三行にまとめると

「クッキー暗号化ミドルウェア」とかいうやつを使う必要があるようです
アプリケーションをラップする機能を提供し、タマネギのようにアプリの周囲を包み込む
まるっとコピペしてもらえれば動きは確認できると思います
CakePHP3でCookieを使用する場合はCookieコンポーネントを使えば良かったのですが、どうやらこの機能はバージョン3.5で撤廃になってしまったようです。

僕が確認した限りではバージョン3.5.8の中にもCookieComponent.phpというファイルはあったのですが、ファイルはあるけど機能はしなくなったってことなんですかね……? まだギリギリ非推奨にとどまってる感じなのかな。

いずれにしろ、今後CakePHP3の最新バージョンでCookieを使いたい場合はコンポーネントではなく「クッキー暗号化ミドルウェア」とかいうやつを使う必要があるようです。

正確に言うと別にコンポーネントを使わなくてもCookie自体は使えるのですが(少なくともバージョン3.5.8では)、セキュリティを高めるために暗号化した情報をCookieに持たせるにはそのミドルウェアを使う必要があるって感じです。



まずはクッキー暗号化ミドルウェアを使わないでCookieの読み書きを行ってみましょう。

コンポーネントがなくなったので、Cookieの書き込みはレスポンスオブジェクトの「cookie()」メソッドを使います。

class SampleController extends AppController {
  function index() {
    $this->response->cookie([
      'name' => 'testCookie',
      'value' => 'クッキーの中身',
      'expire' => strtotime('+1 month'),
      'secure' => true,
    ]);
  }
}

「name」にCookieの名前、「value」にCookieの値を入れます。「expire」は有効期限のタイムスタンプです。上記の例だと一ヶ月後まで有効ってことですね。「secure」はtrueにするとhttpsでのみ有効になります。

一応これで問題はないっぽいのですが、ドキュメントによるとバージョン3.4.0以降は「withCookie()」メソッドを使ってください的なことが書いてあるので、そっちを使った場合はこうなります。

class SampleController extends AppController {
  function index() {
    $this->response = $this->response->withCookie('testCookie', [
      'value' => 'クッキーの中身',
      'expire' => strtotime('+1 month'),
      'secure' => true,
    ]);
  }
}

「withCookie()」の場合はCookie名を第一引数にセットします。あとたぶんだけど返り値を「$this->response」に入れ直さないといけない。



読み込みはリクエストオブジェクトの「getCookie()」メソッドを使う。

$cookie = $this->request->getCookie('testCookie');

もしCookieの値に配列を入力した場合は中身がJSONデータになってるので、json_decode()を使って配列に戻してください。



ミドルウェアを使う

公式のドキュメントによれば、ミドルウェアとはアプリケーションをラップする機能を提供し、タマネギのようにアプリの周囲を包み込むそうです。うーむなるほど。ちょっと何言ってるか分かんない。ロールキャベツではなくタマネギなのん?

CakePHP3のミドルウェア

まあとにかく、クッキー暗号化ミドルウェアを使えるようにするには、まずアプリケーションでミドルウェアを有効にする必要があります。

CakePHP3の新しいバージョンでは、srcフォルダの中に「Application.php」というファイルが入っています。その中を見ると「middleware()」というメソッドがある。ここでクッキー暗号化ミドルウェアを有効化します。

//Application.php
use Cake\Http\Middleware\EncryptedCookieMiddleware;//追加

class Application extends BaseApplication {
  public function middleware($middlewareQueue) {
    //追加
    $cookies = new EncryptedCookieMiddleware(['testCookie'], Configure::read('Security.cookieKey'));
    $middlewareQueue->add($cookies);
  }
}

「EncryptedCookieMiddleware()」の第一引数に暗号化させたいCookieのクッキー名を配列で入力します。

第二引数は暗号化に使うキーを設定します。直接何らかの値を書いても良いのでしょうが、ドキュメントにならって今回は「Configure::read(‘Security.cookieKey’))」としました。この場合はapp.phpで「Security.cookieKey」の値を設定する必要があります。

//app.php
'Security' => [
  'cookieKey' => env('SECURITY_COOKIE_KEY', '任意の文字列'),
],



これでミドルウェアが有効になりました。あとは先ほどと同じように「withCookie()」を使えば暗号化したデータを書き込むことができます。

クッキー暗号化ミドルウェアを使って配列をCookieに保存した場合はjson_decode()を使わなくてもオッケーです。JSONになってないのか、あるいはミドルウェアがJSONのデコードまでやってくれているのかはちゃんと調べてないですが、とりあえずgetCookie()で取り出した時点で値が配列になってます。

//ミドルウェアを使わない場合
$cookie = $this->request->getCookie('testCookie');
$cookie = json_decode($cookie, true);//この時点で配列になる

//ミドルウェアを使う場合
$cookie = $this->request->getCookie('testCookie');//この時点で配列になる






ミドルウェアとかよく分からない概念が急に出てきたもんで、ぶっちゃけあまり理解はできてないです。だから言葉の説明はおかしなことを言っちゃってるかもしれません。

コードはちゃんと自分で動作確認できたものを書いてますんで、とりあえずまるっとコピペしてもらえれば動きは確認できると思います。



その他のCakePHP3を触ってみましたの記事はこちら
まとめという名の箸休め
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください