LoginSignup
55
50

More than 5 years have passed since last update.

FuelPHPでセッション共有時の注意点

Posted at

TL;DR

FuelPHPでセッション情報をMemcacheやRDBMSなどを使って複数ノードで共有する場合には、

  • app/config/crypt.php

を複数ノードで同じ値となるように設定する必要がある。

背景

Webアプリを複数ノードで構成して、ロードバランサでセッション維持をしない場合には、どのノードにユーザの再アクセスがあってもセッションを維持するために、セッションストアとしてMemcacheやRDBMSなどを使うと思います。
例えば、以下のような構成。
AWS Design.png

このような構成を FuelPHP で行う場合の注意点を書いておきます。
図と、以降の説明では ElastiCache(Redis)を使っていますが、注意点についてはRDBMSだろうが普通のMemcacheだろうが同じです。

セッションストアの指定

FuelPHP では、セッションストアの指定を app/config/session.php でまず指定します。(なお、環境に応じて設定を変更したい場合は、 config/staging/session.php などに記述すればOK)

Redisを使うのであれば、session.phpの記述は以下のようになります。

session.php
<?php

return array(
    'driver' => 'redis',
    'redis' => array(
        'cookie_name' => 'fuelrid',
        'database' => 'default',
    ),
);

さらにRedisの場合は、db.phpに接続先の情報を記述します。

db.php
<?php

return array(
        'redis' => array(
            'default' => array(
                'hostname' => 'xxxxxx.yyyyyy.nnnn.apne1.cache.amazonaws.com',
                'port' => 6379,
                'timeout' => null,
            )
        ),
);

セッションストアとして他のシステムを使う場合はなどは、下記公式ドキュメントを参照するとよいです。

暗号キー設定

で、ここからが重要で、これだけの設定だけでは、本質的にはセッションの共有ができません。
ロードバランサが別ノードに新たにリクエストを振るたびに、セッションが維持できないという症状がでます。(環境の作り方次第では、下記情報が同じになっているので、意図せず正しくは動作することもあります)

これは、FuelPHP ではセッションIDをCookie名に設定する時に暗号化を行っているのですが、この時に使用する暗号キーがノード毎に異なることが原因です。
この暗号キーはデフォルトでは設定されておらず、必要となったときに初めて app/config/crypt.php に自動的に生成されます。

ファイルの内容は以下のようなものです。

php.crypt.php
<?php
return array(
  'crypto_key' => '9eEBP8okkcz4xAo9rU5h4f7Q',
  'crypto_iv' => 'HncqRUWjEl2Y53sqawnK4Y7Q',
  'crypto_hmac' => 'ra4OxkVxYthofVMlAk0ncQrQ',
);

この内容を複数のノードで同じとなるようにします。

crypto_key, crypto_iv, crypto_hamc の3つが必要となり、それぞれ以下の条件を満たす必要があります。そうでなければ、再作成されてしまいノード毎に異なることになってしまします。

  • base64デコード可能な文字列
  • 文字列の長さは4の倍数

core/classes/crypt.php の _init() メソッドを見るとわかると思います。

そこからの抜粋で下記のようなコードで暗号キーに必要な値を生成できます。

<?php

function safe_b64encode($value)
{
    $data = base64_encode($value);
    $data = str_replace(array('+','/','='), array('-','_',''), $data);
    return $data;
}


$crypto = '';
for ($i = 0; $i < 8; $i++)
{
    $crypto .= safe_b64encode(pack('n', mt_rand(0, 0xFFFF)));
}

echo $crypto . "\n";

参考

55
50
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55
50