Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

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";

参考

takakiku
記事ははてなブログによせることにしました。 なので、今後は http://kikumoto.hatenablog.com/ でおなしゃす!
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした