Express Session - Express.js

  • 作成日:
  • 最終更新日:2025/07/31

パッケージのインストール

パッケージをインストールするには、以下のコマンドを実行します。

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)