Edited at

Node.js+Express+MongoDBでSessionを利用してログイン機能を実装

More than 5 years have passed since last update.

Node.jsでのセッションの使い方の勉強です.

jadeでやってるサンプルが多いですが,jadeはイマイチ直感的に書けない(慣れない)のでテンプレートエンジンはejsを使います.

勉強中なので自分が理解出来るように解説してみます.

参考: Expressでログイン機能を作る - uchida75cmの日記

参考: Node.js + Express でログイン認証機能を実装する - Devlog


バージョン

node v0.10.23

express 3.4.8

npm 1.3.17

MongoDB shell version: 2.4.8


まずはプロジェクト作成

$ express -e login

$ cd login

$ npm install

$ node app.js

とりあえずブラウザからhttp://lobalhost:3000にアクセスして確認してみましょう.エラーが無く,Expressの文字が表示されればOKです.


MongoDB関連モジュールのインストール

MongoDBを利用するためのモジュールをインストールしておきましょう.調べると出てきますがmongooseはよく使われているみたいです.

$ npm install mongoose

$ npm install connect-mongo


MongoDB起動

ターミナルをnode.jsとは別プロセス(別なタブやウィンドウ)で起動しましょう.

プロジェクトフォルダ内にdbフォルダを作成し,--dbpathオプションでdbフォルダを保存先に指定するようにしました.

$ mkdir db

$ mongod --nojournal --noprealloc --dbpath db


app.js


connect-mongoの読み込み

app.jsの上部のrequire()の部分に以下を追記します.

var MongoStore = require('connect-mongo')(express);


セッションを使う準備

sessionを使うためにはcookieを読み込む必要があるらしいのでapp.use(app.router);の前に以下を追記します.

app.use(express.cookieParser()); //追加

app.use(express.session({
secret: 'secret',
store: new MongoStore({
db: 'session',
host: 'localhost',
clear_interval: 60 * 60
}),
cookie: {
httpOnly: false,
maxAge: new Date(Date.now() + 60 * 60 * 1000)
}
})); //追加


認証用のバリデーター関数

セッションに値が無ければ/loginにリダイレクトさせます.ルーティング設定の前に記述しています.

var loginCheck = function(req, res, next) {

if(req.session.user){
next();
}else{
res.redirect('/login');
}
};


ルーティング設定

ルーティング設定はこんな感じです.↑で記述したloginCheck関数を咬ますことで認証必須のページと認証無しで見れるページを切り分けます.

app.get('/', loginCheck, routes.index);

app.get('/login', routes.login);
app.post('/add', routes.add);
app.get('/logout', function(req, res){
req.session.destroy();
console.log('deleted sesstion');
res.redirect('/');
});


model

app.jsと同じ階層にmodel.jsを作成しましょう.

Model定義をしています.

-db名:user

-collection名:info(UserSchema)

最後の行のexports.Userで他のファイルからModelを呼び出せるようにしています.

var mongoose = require('mongoose');

var url = 'mongodb://localhost/user';
var db = mongoose.createConnection(url, function(err, res){
if(err){
console.log('Error connected: ' + url + ' - ' + err);
}else{
console.log('Success connected: ' + url);
}
});

// Modelの定義
var UserSchema = new mongoose.Schema({
email : String,
password : String
},{collection: 'info'});

exports.User = db.model('User', UserSchema);


controller


routes/index.js

var model = require('../model.js')で↑で定義したmodelの情報を読み込みます.

User = model.User;とすることで↑のUserSchemaがroutes/index.jsでも使えるようになります.

また,sessionの情報はreq.sessionに入っているのでconsole.log()などで確認してみるとわかると思います.

/*モデル読み込み*/

var model = require('../model.js'),
User = model.User;

/*ログイン後ページ*/
exports.index = function(req, res){
res.render('index', { user: req.session.user});
console.log(req.session.user);
};

/*ユーザー登録機能*/
exports.add = function(req, res){
var newUser = new User(req.body);
newUser.save(function(err){
if(err){
console.log(err);
res.redirect('back');
}else{
res.redirect('/');
}
});
};

/*ログイン機能*/
exports.login = function(req, res){
var email = req.query.email;
var password = req.query.password;
var query = { "email": email, "password": password };
User.find(query, function(err, data){
if(err){
console.log(err);
}
if(data == ""){
res.render('login');
}else{
req.session.user = email;
res.redirect('/');
}
});
};


view

あとはフォームなどを作ればOKです.


views/login.ejs

ログイン前のページです.

<!doctype html>

<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ログイン前</title>
</head>
<body>
<h2>ログイン</h2>
<form action="/login" method="GET">
<input type="text" name="email" placeholder="Email"/>
<input type="password" name="password" placeholder="Password"/>
<input type="submit">ログイン</button>
</form>

<h2>新規登録</h2>
<form action="/add" method="POST">
<input type="text" name="email" placeholder="Email"/>
<input type="password" name="password" placeholder="Password"/>
<input type="submit">新規登録</button>
</form>
</body>
</html>


画面例 /login


views/index.ejs

ログイン後のページです.

<!doctype html>

<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ログイン後</title>
</head>
<body>
<h1>My Site</h1>
<p>Welcome to My Site</p>
<%= user %> さんようこそ。
<p>
<a href="/logout">ログアウト</a>
</p>
</body>
</html>


画面例 /index


動作確認

ログイン前に/ or /indexにアクセスしようとするとリダイレクトで/loginが表示されると思います.新規登録(特に何も表示されませんが)をしてから新規登録したメールアドレスとパスワードでログインをすると/を見れるはずです.また,ログアウトのリンクを押すとsessionが破棄され/logoinに戻ると思います.

お疲れ様でした〜.