GitHub https://github.com/expressjs/session の README.md の日本語訳です。 コンテナのクラスタ構成をテストする場合に、重要な要素なので理解のために、記事を作成しました。
インスタレーション
これは、npmレジストリで使用可能なNode.jsモジュールです。 インストールは、npm installコマンドを使用して行います。
$ npm install express-session
API
var session = require('express-session')
session(options)
express-sessionはoptionsオブジェクト内のこれらのプロパティを受け入れます。
cookie
セッションID Cookieの設定オブジェクト。デフォルト値は {path: '/'、httpOnly:true、secure:false、maxAge:null} です。 このオブジェクトで設定できるオプションは次のとおりです。
cookie.domain
Domain Set-Cookie属性の値を指定します。デフォルトでは、ドメインは設定されていません。ほとんどのクライアントは、現在のドメインのみに適用するCookieを考慮します。
cookie.expires
Expires Set-Cookie属性の値にDateオブジェクトを指定します。デフォルトでは、有効期限は設定されていません。ほとんどのクライアントはこれを「非永続Cookie」とみなし、Webブラウザアプリケーションを終了するような条件で削除します。
(注)オプションでexpiresとmaxAgeの両方が設定されている場合、オブジェクトに定義されている最後のものが使用されます。
(注)意有効期限オプションは直接設定しないでください。代わりにmaxAgeオプションを使用してください。
cookie.httpOnly
HttpOnly Set-Cookie属性のブール値を指定します。 true の場合、HttpOnly属性が設定されます。それ以外の場合は設定されません。デフォルトでは、HttpOnly属性が設定されています。
これをtrueに設定すると、クライアント側のJavaScriptがdocument.cookieのクッキーを見ることができなくなるので注意が必要です。
cookie.maxAge
Expires Set-Cookie属性を計算するときに使用する数値(ミリ秒単位)を指定します。これは、現在のサーバー時刻を取得し、maxAgeミリ秒をExpires datetimeを計算する値に追加することによって行われます。デフォルトでは、最大経過時間は設定されていません。
(注)オプションでexpiresとmaxAgeの両方が設定されている場合、オブジェクトに定義されている最後のものが使用されます。
cookie.path
パスセットクッキーの値を指定します。デフォルトでは、これはドメインのルートパスである '/'に設定されています。
cookie.sameSite
ブール値または文字列をSameSite Set-Cookie属性の値に指定します。
- trueを指定すると、SameSite属性は厳密に同じサイト強制に対してStrictに設定されます。
- falseはSameSite属性を設定しません。
- 'lax'は、Laxと同じサイト強制用にSameSite属性をLaxに設定します。
- 'none'は、明示的なクロスサイトクッキーのためにSameSite属性をNoneに設定します。
- 'strict'は、SameSite属性を厳密に同じサイト強制に対してStrictに設定します。
さまざまな実施レベルについての詳細は、仕様 https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1.1 にあります。
(注) これはまだ完全に標準化されておらず、将来変更される可能性がある属性です。 これはまた、多くのクライアントが理解できるまで、この属性を無視する可能性があることを意味します。
cookie.secure
Secure Set-Cookie 属性のブール値を指定します。 true の場合、Secure 属性が設定されます。そうでない場合は、Secure 属性は設定されません。 デフォルトでは、Secure 属性は設定されていません。
これを true に設定すると、ブラウザに HTTPS 接続がない場合、準拠しているクライアントは将来、クッキーをサーバーに戻さないので注意してください。
secure:true が推奨されます。 ただし、https 対応のウェブサイトが必要です。つまり、安全な Cookie には HTTPS が必要です。 secure が設定されていて、HTTP 経由でサイトにアクセスすると、cookie は設定されません。 node.js がプロキシの背後にあり、secure:true を使用している場合、express で「 trust proxy 」を設定する必要があります。
var app = express()
app.set('trust proxy', 1) // trust first proxy
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}))
本番環境で安全なCookieを使用しているが、開発中のテストを可能にする場合は、ExpressのNODE_ENVに基づいてこの設定を有効にする例を以下に示します。
var app = express()
var sess = {
secret: 'keyboard cat',
cookie: {}
}
if (app.get('env') === 'production') {
app.set('trust proxy', 1) // trust first proxy
sess.cookie.secure = true // serve secure cookies
}
app.use(session(sess))
cookie.secure オプションを特別な値 'auto'に設定して、この設定が接続の決定されたセキュリティと自動的に一致するようにすることもできます。 サイトが HTTP と HTTPS の両方で使用可能な場合は、Cookie が HTTPS に設定されると HTTP 経由で表示されなくなるため、この設定を使用する場合は注意が必要です。 これは、エクスプレスの「トラストプロキシ」設定が、開発とプロダクションの設定を簡素化するために適切に設定されている場合に便利です。
genid
新しいセッションIDを生成するために呼び出す関数。 セッションIDとして使用される文字列を返す関数を提供します。 この関数は、IDを生成するときにreqに付加された値を使用したい場合は、最初の引数としてreqを与えます。
デフォルト値は、uid-safeライブラリを使用してIDを生成する関数です。
(注) セッションが競合しないように、一意のIDを生成するように注意してください。
app.use(session({
genid: function(req) {
return genuuid() // use UUIDs for session IDs
},
secret: 'keyboard cat'
}))
name
レスポンスに設定するセッションIDクッキーの名前(リクエストから読み取る)。
デフォルト値は 'connect.sid'です。
(注) 複数のアプリが同じホスト名で実行されている場合(名前はlocalhostまたは127.0.0.1で、異なるスキームとポートで異なるホスト名を指定しない場合)、セッションCookieを互いに分離する必要があります。 最も簡単な方法は、アプリごとに異なる名前を設定することです。
proxy
secure cookies を設定するときは、リバースプロキシを信頼してください( "X-Forwarded-Proto"ヘッダー経由)。
デフォルト値は未定義です。
- true "X-Forwarded-Proto"ヘッダーが使用されます。
- false 直接のTLS / SSL接続がある場合のみ、すべてのヘッダーが無視され、接続は安全であるとみなされます。
- undefined expressで "trust proxy"設定を使用してください。
resave
要求中にセッションが変更されなかった場合でも、セッションをセッションストアに強制的に保存します。 あなたのセッションストアに依存して必要かもしれませんが、クライアントがあなたのサーバーに対して2つの並行した要求を行い、1つの要求でセッションに加えられた変更が、変更を加えなくても他の要求が終了したときに上書きされる (この動作は、使用しているセッションストアによっても異なります)。
デフォルト値は true ですが、デフォルトを使用することは推奨されなくなりました。 この設定を調べて、ユースケースに適したものを選択してください。 通常、あなたは false を望むでしょう。
これが私のセッションストアに必要かどうか私はどのように知る事ができますか? 最善の方法は、タッチメソッドを実装しているかどうかを確認することです。 そうであれば、resave:falseを安全に設定できます。 タッチメソッドが実装されておらず、ストアでセッションが有効期限に設定されている場合は、resave:trueが必要になる可能性があります。
rolling
すべてのレスポンスにセッション識別子クッキーを強制的に設定します。 有効期限が元の maxAge にリセットされ、有効期限のカウントダウンがリセットされます。
デフォルト値は false です。
メモこのオプションが true に設定されていても、saveUninitialized オプションが false に設定されている場合、セッションは初期化されていないレスポンスにクッキーは設定されません。
saveUninitialized
「初期化されていない」セッションを強制的にセッション・ストアに保存します。 セッションは新規であるが変更されていないときは初期化されません。 falseを選択すると、ログインセッションの実装、サーバーストレージの使用量の削減、またはCookieを設定する前に許可が必要な法令の遵守に役立ちます。 falseを選択すると、クライアントがセッションなしで複数のパラレル要求を行う競合条件の助けとなります。
デフォルト値はtrueですが、デフォルトを使用することは推奨されなくなりました。 この設定を調べて、ユースケースに適したものを選択してください。
(注)PassportJSと共にSessionを使用している場合、Passportは、ユーザーが認証された後で使用するために空のPassportオブジェクトをセッションに追加します。このオブジェクトは、セッションの変更として扱われ、保存されます。 これはPassportJS 0.3.0で修正されています。
secret
必須オプション
これは、セッションID Cookieに署名するために使用される秘密です。 これは、単一のシークレットの文字列か、複数のシークレットの配列のいずれかです。 秘密の配列が提供されている場合、最初の要素のみがセッションIDクッキーの署名に使用され、要求の署名を検証するときはすべての要素が考慮されます。
store
セッションストアインスタンスは、デフォルトで新しいMemoryStoreインスタンスになります。
unset
req.session の設定を解除する(delete、nullに設定するなどによって)結果を制御します。
デフォルト値は 'keep'です。
- 'destroy'セッションは、応答が終了すると破棄(削除)されます。
- 'keep'ストア内のセッションは保持されますが、要求中に行われた変更は無視され、保存されません。
req.session
セッションデータを格納またはアクセスするには、要求プロパティreq.sessionを使用します。これは、通常はストアでJSONとして(一般的に)シリアル化されているため、ネストされたオブジェクトは一般的に問題ありません。 たとえば、次のようなユーザー固有のビューカウンタがあります。
// Use the session middleware
app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))
// Access the session as req.session
app.get('/', function(req, res, next) {
var sess = req.session
if (sess.views) {
sess.views++
res.setHeader('Content-Type', 'text/html')
res.write('<p>views: ' + sess.views + '</p>')
res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>')
res.end()
} else {
sess.views = 1
res.end('welcome to the session demo. refresh!')
}
})
Session.regenerate(callback)
セッションを再生成するには、単にメソッドを呼び出します。 完了すると、req.sessionで新しいSIDとSessionインスタンスが初期化され、コールバックが呼び出されます。
req.session.regenerate(function(err) {
// will have a new session here
})
Session.destroy(callback)
セッションを破棄し、req.sessionプロパティの設定を解除します。 完了すると、コールバックが呼び出されます。
req.session.destroy(function(err) {
// cannot access session here
})
Session.reload(callback)
セッション・ストアからセッションデータをリロードし、req.sessionオブジェクトを再設定します。 完了すると、コールバックが呼び出されます。
req.session.reload(function(err) {
// session updated
})
Session.save(callback)
セッションをセッション・ストアに保存して、セッション・ストア内の内容をメモリの内容に置き換えます(ただし、セッション・ストアでは別の処理が行われる可能性があります。正確な動作については、セッション・ストアのドキュメントを参照してください)。
このメソッドは、セッションデータが変更されていればHTTPレスポンスの最後に自動的に呼び出されます(ただし、この動作はミドルウェアコンストラクタのさまざまなオプションで変更できます)。 このため、通常はこのメソッドを呼び出す必要はありません。
このメソッドを呼び出すと便利な場合があります。たとえば、長寿命リクエストや WebSocket などです。
req.session.save(function(err) {
// session saved
})
Session.touch()
.maxAgeプロパティを更新します。 セッションミドルウェアがこれを行うので、通常はこれを呼び出す必要はありません。
req.session.id
各セッションには、固有のIDが関連付けられています。 このプロパティはreq.sessionIDのエイリアスであり、変更することはできません。 セッションIDをセッションオブジェクトからアクセス可能にするために追加されています。
req.session.cookie
各セッションには固有の Cookie オブジェクトが付いています。 これにより、訪問者ごとにセッション Cookie を変更することができます。 たとえば、req.session.cookie.expires を false に設定すると、cookie が user-agent の間だけ残ることができます。
Cookie.maxAge
あるいは、req.session.cookie.maxAgeは残りの時間をミリ秒単位で返します。新しい値を再割り当てして.expiresプロパティーを適切に調整することもできます。 以下は本質的に同等です
var hour = 3600000
req.session.cookie.expires = new Date(Date.now() + hour)
req.session.cookie.maxAge = hour
たとえば、maxAge が 60000(1分)に設定され、30秒が経過すると、現在の要求が完了するまで30000が返されます。req.session.touch()が呼び出され、req.session.maxAgeの値が、リセットされます。
req.session.cookie.maxAge // => 30000
req.sessionID
ロードされたセッションのIDを取得するには、要求プロパティ req.sessionID にアクセスします。 これは、セッションがロード/作成されるときに設定される読み取り専用の値です。
セッション・ストアの実装
すべてのセッションストアはEventEmitterで、特定のメソッドを実装する必要があります。 以下のメソッドは、必須、推奨、およびオプションのリストです。
- Required methods は、このモジュールが常にストアで呼び出すメソッドです。
- Recommended methods は、利用可能であれば、このモジュールが店舗で呼び出す方法です。
- Optional methods は、このモジュールがまったく呼び出さないメソッドですが、ユーザーに均一なストアを提示するのに役立ちます。
実装例では、connect-redis repoを表示します。
store.all(callback)
任意
このオプションのメソッドは、セッション・ストア内のすべてのセッションを配列として取得するために使用されます。 コールバックは、コールバック(エラー、セッション)として呼び出される必要があります。
store.clear(callback)
任意
このオプションのメソッドは、セッション・ストアからすべてのセッションを削除するために使用されます。 コールバックは、ストアがクリアされるとコールバック(エラー)として呼び出される必要があります。
store.length(callback)
任意
このオプションのメソッドは、セッション・ストア内のすべてのセッションの数を取得するために使用されます。 コールバックはコールバック(error、len)として呼び出される必要があります。
store.get(sid, callback)
必須
この必須メソッドは、セッションID(sid)を指定してストアからセッションを取得するために使用されます。 コールバックはコールバック(エラー、セッション)として呼び出される必要があります。
セッション引数が見つかった場合はセッションでなければなりません。そうでない場合はセッションが見つからない場合(またはエラーがない場合)はnullまたは未定義です。 error.code === 'ENOENT'がコールバック(null、null)のように動作する場合、特殊なケースが作成されます。
store.set(sid, session, callback)
必須
この必須メソッドは、セッションID(sid)およびセッション(セッション)オブジェクトを指定してセッションをセッション・ストアにUPSERTするために使用されます。 セッションがセッション・ストアに設定されると、コールバックはコールバック(エラー)として呼び出されます。 ( UPSERTは、オブジェクトが無ければ追加、あれば更新します。)
store.touch(sid, session, callback)
推奨
この推奨される方法は、セッションID(sid)とセッション(セッション)オブジェクトを指定して、与えられたセッションに " touch" ために使用されます。 コールバックは、セッションに触れたらコールバック(エラー)として呼び出す必要があります。
これは主に、セッション・ストアがアイドルセッションを自動的に削除するときに使用され、このメソッドを使用して、指定されたセッションがアクティブであることをストアに通知し、潜在的にアイドルタイマーをリセットします。
互換のあるセッション・ストア
このモジュールと互換性のあるセッション・ストアを実装しています。 モジュールを追加するためにPRをしてください:)
★ aerospike-session-store A session store using Aerospike.
★ cassandra-store An Apache Cassandra-based session store.
★ cluster-store A wrapper for using in-process / embedded stores - such as SQLite (via knex), leveldb, files, or memory - with node cluster (desirable for Raspberry Pi 2 and other multi-core embedded devices).
★ connect-azuretables An Azure Table Storage-based session store.
★ connect-cloudant-store An IBM Cloudant-based session store.
★ connect-couchbase A couchbase-based session store.
★ connect-datacache An IBM Bluemix Data Cache-based session store.
★ connect-db2 An IBM DB2-based session store built using ibm_db module.
★ connect-dynamodb A DynamoDB-based session store.
★ connect-loki A Loki.js-based session store.
★ connect-ml A MarkLogic Server-based session store.
★ connect-mssql A SQL Server-based session store.
★ connect-monetdb A MonetDB-based session store.
★ connect-mongo A MongoDB-based session store.
★ connect-mongodb-session Lightweight MongoDB-based session store built and maintained by MongoDB.
★ connect-pg-simple A PostgreSQL-based session store.
★ connect-redis A Redis-based session store.
★ connect-memcached A memcached-based session store.
★ connect-memjs A memcached-based session store using memjs as the memcached client.
★ connect-session-knex A session store using Knex.js, which is a SQL query builder for PostgreSQL, MySQL, MariaDB, SQLite3, and Oracle.
★ connect-session-sequelize A session store using Sequelize.js, which is a Node.js / io.js ORM for PostgreSQL, MySQL, SQLite and MSSQL.
★ express-mysql-session A session store using native MySQL via the node-mysql module.
★ express-oracle-session A session store using native oracle via the node-oracledb module.
★ express-sessions: A session store supporting both MongoDB and Redis.
★ connect-sqlite3 A SQLite3 session store modeled after the TJ's connect-redis store.
★ documentdb-session A session store for Microsoft Azure's DocumentDB NoSQL database service.
★ express-nedb-session A NeDB-based session store.
★ express-session-cache-manager A store that implements cache-manager, which supports a variety of storage types.
★ express-session-level A LevelDB based session store.
★ express-etcd An etcd based session store.
★ fortune-session A Fortune.js based session store. Supports all backends supported by Fortune (MongoDB, Redis, Postgres, NeDB).
★ hazelcast-store A Hazelcast-based session store built on the Hazelcast Node Client.
★ level-session-store A LevelDB-based session store.
★ medea-session-store A Medea-based session store.
★ mssql-session-store A SQL Server-based session store.
★ nedb-session-store An alternate NeDB-based (either in-memory or file-persisted) session store.
★ sequelstore-connect A session store using Sequelize.js.
★ session-file-store A file system-based session store.
★ session-rethinkdb A RethinkDB-based session store.
参考例
express-session を使用してユーザーのページビューを格納する簡単な例
var express = require('express')
var parseurl = require('parseurl')
var session = require('express-session')
var app = express()
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}))
app.use(function (req, res, next) {
var views = req.session.views
if (!views) {
views = req.session.views = {}
}
// get the url pathname
var pathname = parseurl(req).pathname
// count the views
views[pathname] = (views[pathname] || 0) + 1
next()
})
app.get('/foo', function (req, res, next) {
res.send('you viewed this page ' + req.session.views['/foo'] + ' times')
})
app.get('/bar', function (req, res, next) {
res.send('you viewed this page ' + req.session.views['/bar'] + ' times')
})
ライセンス
MIT