LoginSignup
277
277

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-02-03

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に戻ると思います.

お疲れ様でした〜.

277
277
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
277
277