インターネットを調べて見ると、いろいろと分かるCSRF対策。
いざ、やってみるとなかなかうまく行かないので、メモとして投稿します。
CSRFミドルウェアのインストール
npm install csrf --save
express-sesionのインストール
npm install express-session --save
app.jsでexpress-sessionを読み込む
app.js
var session = require('express-session');
ルーティング定義ファイルを読み込む
app.js
//ログインページに実装する(という想定)
var loginRouter = require('./routes/login');
express-sessionモジュールを設定
ルーティングモジュールの設定より前に行うのがポイント。
後に行うと、reqにsessionが設定されず、undefinedとなる。
app.js
//express-sessionモジュールを設定する
app.use(session({
//暗号化に利用するキーを設定
secret: 'secret key',
//毎回セッションを作成しない
resave: false,
//未初期化状態のセッションを保存しない
saveUninitialized: false,
cookie: {
//生存期間は3日
maxAge: 3 * 24 * 60 * 1000,
//httpsを使用しない
secure: false
}
}));
ルーティングモジュールを設定
app.js
app.use('/login', loginRouter);
login.jsモジュールでCSRF対策を行う
login.js
var express = require('express');
var router = express.Router();
//CSRFミドルウェアを生成する
var csrf = require('csrf');
var tokens = new csrf();
router.get('/', function(req, res) {
//新規で秘密文字とトークンを生成する
var secret = tokens.secretSync();
var token = tokens.create(secret);
//秘密文字をセッションに保存する
req.session._csrf = secret;
//トークンをCookieに保存する
res.cookie('_csrf', token);
res.render('login');
});
router.post('/', function(req, res){
//秘密文字をセッションから取得する
var secret = req.session._csrf;
//トークンをCookieから取得する
var token = req.cookies._csrf;
//秘密文字とトークンの組み合わせが正しいかチェックする
if(tokens.verify(secret, token) === false)
{
throw new Error('Invalid Token');
}
//使用済みの秘密文字を削除する
delete req.session._csrf;
//使用済みのトークンを削除する
res.clearCookie('_csrf');
});
module.exports = router;