なんでMongoDBでセッション管理するのか
Node.js + Express (Connect) で標準で提供されている MemoryStore でセッション管理を行うとメモリ上での管理になるため node が落ちるとセッションデータが消えることになりセッションの永続化ができませんし、動作確認もソースの確認も行っていませんが、production で起動した際に出力されるメッセージ(https://github.com/senchalabs/connect/blob/master/lib/middleware/session.js#L199)に
Warning: connection.session() MemoryStore is not designed for a production environment, as it will leak memory, and will not scale past a single process.
とあり、どうやらメモリリークするらしいです。
そこで Node.js (JavaScript) と相性のいいNoSQLデータベースのオープンソース実装であるMongoDBでセッション管理を行います。MongoDB で Node.js + Express (Connect) のセッション管理を行うために connect-mongo パッケージを使用します。
今回使用する MongoDB では connect-mongo を使用しますが、Amazon DynamoDB で connect-dynamodb、Redis で connect-redis を使用するなど、他にもいくつかの選択肢が存在します。
検証環境
- Node.js 0.8.12
- Express 3.0.0rc5
- connect-mongo 0.2.0
モジュールの読み込み
var express = require('express'); var app = express(); var MongoStore = require('connect-mongo')(express);
セッションストアの設定
app.configure(function(){ // セッションIDをクライアントの cookie にセットするので必要 app.use(express.cookieParser()); // セッションストアを設定 app.use(express.session({ secret: 'topsecret', store: new MongoStore({ db: 'databaseName', // require host: 'databaseHost', // default: 127.0.0.1 username: 'username', // optional password: 'password', // optional clear_interval: 60 * 60 // Interval in seconds to clear expired sessions. 60 * 60 = 1 hour }), cookie: { httpOnly: false, // 60 * 60 * 1000 = 3600000 msec = 1 hour maxAge: new Date(Date.now() + 60 * 60 * 1000) } })); });
セッションの設定は以上です。Node.js の待ち受けポートにアクセスすると無条件でセッションが開始され、MongoDB の databaseName.sessions コレクションにセッションデータが作成されます。
セッションの操作
request.session.name = 'value'; // 値の設定 delete request.session.name; // 値の破棄 request.session.destroy(); // セッションの破棄
セッションIDの生成ロジック
ところで、Connect のセッション管理の中で、どのようなロジックでセッションIDが生成され、パラメータとして渡している secret が使用されているかというと、(Connect 2.5.0のソースを確認)
生成されたセッションIDをキーにしてメモリやDBに保存されますが、これがこのままブラウザに渡されるわけではありません。
こうして生成(sign)されたIDがブラウザに渡され、実際に使用するときには上記の逆の手順をふみ(unsign)、セッションIDが同一secretで生成されていることを保証、つまりセッションIDの改竄検出が行われています。パラメータ secret の目的はこの改竄検出ということになります。
また、このセッションID生成ロジックを外部から変更する(セッションIDの生成ロジックをより望ましい形に変更する)方法は現在の Connect の実装では提供されていないので、もし必要があれば lib/middleware/session.js (https://github.com/senchalabs/connect/blob/master/lib/middleware/session.js#L202) をフォークして実装する以外に手はないようです。他言語/他フレームワークではこの部分は容易に変更できる実装が多い気がしますので、function をパラメータで受けとってくれたりするとうれしいのですけど。
参考
Node.js v0.8 APIリファレンス http://nodejs.jp/nodejs.org_ja/docs/v0.8/api/
Express APIリファレンス http://expressjs.com/api.html
connect-mongo GitHub https://github.com/kcbanner/connect-mongo
Connect リファレンス http://www.senchalabs.org/connect/