パッケージのインストール
パッケージをインストールするには、以下のコマンドを実行します。
npm install express-session
オプション
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: false,
cookie:{
httpOnly: true,
secure: false,
maxAge: 1000 * 60 * 30
}
}));
secret は、指定した文字列を使ってクッキー ID を暗号化し、クッキー ID が書き換えらているかを判断します。
resave は、セッションにアクセスすると上書きされます。
saveUninitialized は未初期化状態のセッションも保存します。
httpOnly は、クライアント側でクッキー値を見れない、書きかえれないようにします。
secure は、secure属性の設定です。
Cookie の Secure属性とは、「 HTTPS 通信時のみ Cookie を送信する 」という設定です。
maxAge は、セッションを破棄する時間を設定します。
- httpOnly
-
httpOnly は、クライアント側でクッキー値を見れない、書きかえれないようにします。
httpOnly: trueにすると、javascript で読み取り不可になります。
- secure
-
https のみ許可します。
secure: trueにすると、https 接続のみ許可します。
- resave
-
セッションが変更されていなくても、毎回セッションを保存するかどうかを指定します。
resave: falseにすると、セッションが変更された場合にのみ保存されるため、ストレージへのアクセスを削減できます。
- saveUninitialized
-
新しく作成されたセッションオブジェクトを、内容が何も設定されていなくても保存するかどうかを指定します。
saveUninitialized: falseにすると req.session に値を設定するまではセッションストアに保存されません。クッキーも発行されません。実際にセッションが「使われた」と判断されたときだけ保存されます。
saveUninitialized: trueにするとログインなど何もしていなくても、アクセスしただけでセッションID付きクッキーが発行されます。
多くの場合はfalseを使うのが適切です。セッションIDをすぐに必要とする訪問者カウントの機能を使う場合は便利。
- rolling
-
リクエストごとにセッションの有効期限(cookieの有効期限)をリセットするかどうかを指定します。
rolling: trueにするとリクエストがあるたびに セッションの有効期限を延長(リセット) します。
セッション有効期限を 10 分にして rolling: true に設定すると、ユーザーが最後にアクセスしてから 10 分経ったときにだけセッションが切れます。
app.use(session({ secret: 'yourSecret', resave: false, saveUninitialized: false, rolling: true, cookie: { maxAge: 10 * 60 * 1000 } // 10分 }));
上記の場合は、15分間アクセスがなければ自動ログアウト、アクセスがあれば延長となります。
使い分けは以下の表を参考
設定 動作 使いどころ true アクセスのたびに期限をリセット 常にアクティブなユーザーに対応、ログイン中に勝手にログアウトしてほしくないとき false 最初のアクセスから一定時間で期限(maxAgeの期限で強制破棄) セッション時間を厳格に管理したい、セキュリティ重視のとき
- SameSite
-
セッションIDを含むクッキーが「クロスサイトリクエスト」に対して送信されるかどうかをしていします。
ドキュメントでは設定値は以下のような説明になっています。
- true will set the SameSite attribute to Strict for strict same site enforcement.
- false will not set the SameSite attribute.
- 'lax' will set the SameSite attribute to Lax for lax same site enforcement.
- 'none' will set the SameSite attribute to None for an explicit cross-site cookie.
- 'strict' will set the SameSite attribute to Strict for strict same site enforcement.
- true は、SameSite属性を Strict に設定し、厳格なSameSiteポリシーを適用します。
- false は、SameSite属性を設定しません。
- 'lax' は、SameSite属性を Lax に設定し、緩やかなSameSiteポリシーを適用します。
- 'none' は、SameSite属性を None に設定し、クロスサイトでのクッキー送信を明示的に許可します。
- 'strict' は、SameSite属性を Strict に設定し、厳格なSameSiteポリシーを適用します。
※ true と 'strict' は同じ意味になりますが、推奨されるのは文字列で明示的に指定する書き方(例:'strict', 'lax')です。
使い分けは以下の表を参考
設定値 送信条件 利用シーン 注意点 strict 同一サイトのみ セキュリティ最優先の内部システム 連携しにくい lax 通常リンクOK、POSTやJSはNG 一般的なWebアプリ デフォルトでよく使われる none すべてOK(HTTPS必須) 外部サービス連携(OAuth等) secure: true が必須
セッションを使ってみる
「 Express Generator 」でアプリケーションを作成し、以下のようにファイルを変更します。
app.js
var session = require('express-session');
var session_opt = {
secret: 'keyword',
resave: false,
saveUninitialized: false,
cookie: { maxAge: 60 * 60 * 1000}
}
app.use(session(session_opt));
pp.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/form', formRouter);
「 app.use(session(session_opt)); 」は、ルーターの記述よりも前に記述する必要があります。
app.js
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/form', formRouter);
routes/index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
if(req.session.message != undefined) {
msg = req.session.message;
}
res.render('index', { title: 'Express', msg: msg });
});
module.exports = router;
routes/form.js
var express = require('express');
var router = express.Router();
router.get('/', (req, res, next) => {
var msg = "送信してください。";
if(req.session.message != undefined) {
msg = req.session.message;
}
let data = {
title: 'Hello',
content: msg
};
res.render('form', data);
});
router.post('/post', (req, res, next) => {
let msg = req.body['message'];
req.session.message = msg;
let data = {
title: 'Hello',
content: '送信されたデータ:' + msg
};
res.render('form', data);
})
module.exports = router;
views/index.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p><%- msg %></p>
</body>
</html>
views/form.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title><%- title %></title>
</head>
<body>
<p><%- content %></p>
<form action="/form/post" method="post">
<input type="text" name="message">
<input type="submit" value="送信">
</form>
</body>
</html>
「 http://localhost:3000/form 」をブラウザで開きフォームからデータを送信します。
その後、「 http://localhost:3000 」のページを開きます。
フォームから送信されたデータがセッションに保存されているため、画面にフォームから送信された値が表示されます。
ページ遷移での利用
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const session = require("express-session"); // +
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var sessionRouter = require('./routes/session'); // +
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: "secret",
resave: false,
saveUninitialized: true,
}));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/session', sessionRouter); // +
routes/session.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
req.session.message = "hello, world";
res.render('session/index');
});
router.get('/sub', function(req, res, next) {
res.render('session/sub', { message : req.session.message });
});
module.exports = router;
views/session/index.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>index.ejs</title>
</head>
<body>
<p><a href="/session/sub">sub</a></p>
</body>
</html>
views/session/sub.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>sub.ejs</title>
</head>
<body>
<p><%=message %></p>
</body>
</html>
セッションの削除
delete(req.session.message)