express-passportを触ってみる手順書

expressを導入し、passportをためしに触ってみようと思いましたが、案の定初心者の私はハマりましたので、最低限の動作確認ができる手順書をメモとして残します。
ログインボタンを押下したら、passportで処理が動いていることを最低限確認します。

  1. 前提
  2. プロジェクトの準備
  3. 簡単実装
  4. 動作確認

0. 前提

・さくらVPS CentOS7で試しました
・node.js version7.4.0
・express version4.14.0
・passport version0.3.2

1. プロジェクトの準備

1.1. express-generatorの準備

expressのアプリケーションの雛形を簡単に用意できるモジュールのexpress-generatorを使います。
未導入の場合はインストールしてください。-gは適宜外してください。

$npm install -g express-generator

1.2. プロジェクト作成

テスト用アプリケーションのディレクトリを作成したい場所に移動した後、雛形を作成します。
ここでは、testappという名前で進めます。

$express -e testapp

-e は、テンプレートエンジンにejsを使用するオプションですので、好みです。

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

passportをインストールします。

$npm install --save passport

passportでは、ログインの認証方法により、strategyをインストールする必要があります。
今回は、一番単純なpassport-localを使用します。

$npm install --save passport-local

他にインストールしなければいけないものをインストールします。

$npm install

2. 簡単実装

2.1. ログインフォームの実装

今回は、indexページにログインフォームをつけます。
views/index.ejsを以下のように編集してください。
以下はindex.ejsの全体です。

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %></p>
 <!-- ★ここから追加★ --> 
    <form action="/login" method="post">
      <input type="text" name="username" />
      <input type="password" name="password" />
      <input type="submit" value="login">
    </form>
 <!-- ★ここまで追加★ --> 
  </body>
</html>

2.2. ログイン操作のリクエストの処理実装

app.jsを編集します。今回は、最低限の実装を全てapp.jsに詰め込みますので汚い内容です。
以下はapp.jsの全体です。編集箇所には★マークがついています。

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport'); // ★追加
var LocalStrategy = require('passport-local').Strategy; // ★追加

var index = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// ★この段落を新規追加
// passportの認証を実装します。
app.use(passport.initialize());
passport.use(new LocalStrategy(function(username, password, done){
  // ユーザ名aaa パスワードbbbのときだけ認証成功とします
  if(username !== 'aaa' || password !== 'bbb'){
    console.log('login failed');
    return done(null, false);
  }
  console.log('login successed');
  return done(null, username);
}));

app.use('/', index);
app.use('/users', users);

// ★この段落追加
app.post('/login', passport.authenticate('local', {
    // 認証失敗時にはrootページリダイレクトします
    failureRedirect: '/',
    session: false
  }), function(req, res) {
  // 認証成功時にはexpressの雛形のusersページに飛ばします
  res.redirect('users');
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};



  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

3. 動作確認

作ったアプリケーションを起動します。

$npm start

アクセスします。
http://(ipアドレス):3000/

今回は、ユーザ名aaa パスワードbbbを入力したときのみuserページに遷移します。
それ以外の入力の場合はルートページにリダイレクトします。
認証結果はconsoleでも確認できます。

実用に耐えるものを作るために、今後以下が必要ということを認識しています。
・DBへのユーザ情報問い合せ
・セッション
・セキュリティ対策
- パスワードのハッシュ化
- cookieまわり
- http通信まわり
- DBまわり
・エラー処理