connect-mongoをサクッと試す
社内勉強会で「Node.jsを使って社内で使える便利ツールを作ろう」というテーマで簡単なWebアプリケーションの作成を行っている。
Express+MongoDB+ejs(ほぼjQuery)で最低限の機能を実装したモノは出来上がったものの、ユーザー認証機能が未実装のままだったので、ちょっと残念な感じになっていた。
Express ユーザー認証
とかで検索すると、Passport
というパッケージを使うのが定跡なように感じたが、あまり頑張らずにサクッとユーザー認証機能を実装したかったので、今回はconnect-mongo
というパッケージをサクッと試してみることにした。
Expressで認証を設定するプロジェクトの雛形を作成する
事前にexpress-generator
のインストールをしてある前提で、プロジェクトの雛形を作成し、動作確認を行います。
テンプレートエンジンにはejs
を使用した。
$ mkdir connect-mongo-skt && cd connect-mongo-skt $ express -e . $ npm install $ npm start
今回想定するログインのシナリオは、以下の通りです。
未ログイン時
* ルートへのアクセス
↓(リダイレクト)
* ログイン画面
↓(ログイン)
* ユーザーページ
ログイン時
* ルートへのアクセス
↓(リダイレクト)
* ユーザーページ
ユーザー認証に成功すると、ユーザーページへアクセス可能になるという動作に必要なrouterとviewの作成を行います。
express-generator
で作成した雛形には以下のように、indexとusersページが作成されているので、
- index → ログイン画面
- users → ログイン認証に成功されたら表示する画面
追加で、以下のviewを作成しました。(コードは後述)
- login → ログイン前にindexのrouterから呼ばれる
※現時点ではhttp://localhost:3000/users
というアドレスでusersページにアクセス出来る
connect-mongoを導入
必要パッケージのインストール
$ npm install --save connect-mongo $ npm install --save express-session $ npm install --save mongoose
app.jsの変更
パッケージの読み込みとmongooseコネクションの確立
const mongoose = require('mongoose'); const session = require('express-session'); const mongoStore = require('connect-mongo')(session); // localhost:27017 でMongoDBが起動している前提 mongoose.connect('mongodb://localhost:27017/connect-mongo-skt');
sessionを使うための準備
app.use(session({ secret: 'test', store: new mongoStore({ mongooseConnection: mongoose.connection }) }));
後でindex
内でルーティングの設定を一括して行うため以下の部分はコメントアウトします。
// app.use('/users', users);
mongooseのスキーマ定義
$ mkdir models $ touch models/userModel.js
const mongoose = require('mongoose'); let Schema = mongoose.Schema; let UserSchema = new Schema({ username: String, password: String, }); module.exports = mongoose.model('Users', UserSchema);
index.jsの変更
ModelとViewファイルの読み込み
let User = require('../models/userModel.js'); let users = require('./users.js');
router.get('/', function(req, res, next) { // debug console.log(req.session); if (req.session.user) { // すでにログイン時 res.redirect('/users') } res.render('login', { title: 'Express' }); }); /* ログイン */ router.post('/login', function(req, res, next) { // 簡単なバリデーション if (!req.body.username || !req.body.password) { res.redirect('/'); } let query = { username: req.body.username, password: req.body.password // sha1などで暗号化するのがベター } User.find(query, function(err, data) { if (err) { // エラー発生時 console.log(err); res.redirect('/'); } if (data.length > 0) { // ログイン成功時 req.session.user_id = data[0]._id; res.redirect('/users'); } else { // ログイン失敗時 res.redirect('/'); } }); }); router.post('/register', function(req, res) { // 簡単なバリデーション if (!req.body.username || !req.body.password) { res.redirect('/'); } let user = new User(); user.username = req.body.username; user.password = req.body.password; user.save(function(err) { if (err) { console.log(err); } res.redirect('/'); }); }); router.post('/logout', function(req, res) { delete req.session.user; res.redirect('/'); }); let loginCheck = (req, res, next) => { if (req.session.user_id) { next(); } else { res.redirect('/'); } } router.use('/users', loginCheck, users); // loginCheck
ログイン画面
サクッと試す目的で作成したため、ログイン画面とユーザー登録画面が単一になっています。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h2>ログイン</h2> <form action="/login" method="POST"> <input type="text" name="username"/> <input type="password" name="password"/> <input type="submit">ログイン</button> </form> <h2>新規登録</h2> <form action="/register" method="POST"> <input type="text" name="username"/> <input type="password" name="password"/> <input type="submit">登録</button> </form> </body> </html>
以上、connect-mongoを使ってログイン機能をサクッと実装することが出来ました。