tech.chakapoko.com
Home / Node.js / Express

[Node.js][Express]認証機能を実装する

セッションの機能を使って簡単な認証機能を実装できます。

必要なモジュールのインストール

セッションを使うので express-session を、フォームからのリクエストを受けるのでリクエストボディをパースするために body-parser をインストールします。

$ npm install --save express-session body-parser

実装の手順

まず、メインの処理を行う前にセッションをチェックし、セッションにユーザー名が入っていなければログインページにリダイレクトをするミドルウェアを定義します。

app.use((req, res, next) => {
  if (req.session.username) {
    next();
  } else {
    res.redirect('/login');
  }
});

ログインページでは、ユーザー名とパスワードの入力を受け付けたらパスワードを照合し、正しければセッションを生成します。

(当然ですが、実際に運用する時はパスワードのハッシュ化やCSRF対策などを行なってください)

app.get('/login', (req, res) => {
  res
    .type('text/html')
    .send(
      `<form method="POST" action="/login">
         <div>username<input type="text" name="username"></div>
         <div>password<input type="password" name="password"></div>
         <div><input type="submit" name="login"></div>
       </form>`
    )
});

app.post('/login', (req, res) => {
  const username = req.body.username;
  const password = req.body.password;
  if (username === 'admin' && password === 'password') {
    req.session.regenerate((err) => {
      req.session.username = 'admin';
      res.redirect('/');
    });
  } else {
    res.redirect('/login');
  }
});

ログアウトページではリクエストを受けたらセッションを破棄するメソッドを呼びます。

app.get('/logout', (req, res) => {
  req.session.destroy((err) => {
    res.redirect('/');
  });
});

サンプルコードの全体

サンプルコードの全体は次のようになります。

ミドルウェアとルーティング定義の並び順には注意が必要です。

ログインのチェックを行うミドルウェアはログインページへのルーティング定義よりも後ろにおく必要があります。そうでないとログインページを参照するときもログインをチェックされるためにリダイレクトループが発生します。

const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');

const app = express();

const sess = {
  secret: 'secretsecretsecret',
  cookie: { maxAge: 60000 },
  resave: false,
  saveUninitialized: false,
}

if (app.get('env') === 'production') {
  app.set('trust proxy', 1)
  sess.cookie.secure = true
}

app.use(session(sess))

app.use(bodyParser.urlencoded({ extended: true }));

app.get('/login', (req, res) => {
  res
    .type('text/html')
    .send(
      `<form method="POST" action="/login">
         <div>username<input type="text" name="username"></div>
         <div>password<input type="password" name="password"></div>
         <div><input type="submit" name="login"></div>
       </form>`
    )
});

app.post('/login', (req, res) => {
  const username = req.body.username;
  const password = req.body.password;
  if (username === 'admin' && password === 'password') {
    req.session.regenerate((err) => {
      req.session.username = 'admin';
      res.redirect('/');
    });
  } else {
    res.redirect('/login');
  }
});

app.get('/logout', (req, res) => {
  req.session.destroy((err) => {
    res.redirect('/');
  });
});

app.use((req, res, next) => {
  if (req.session.username) {
    next();
  } else {
    res.redirect('/login');
  }
});

app.get('/', (req, res) => {
  res.send('Hello ' + req.session.username);
});

app.listen('3000', () => {
  console.log('Application started');
});